Complete Ethereum DApp with EVM, Remix, GoLang, Truffle, Drizzle and Solidity

Part 1- Car Auction DAPP

Ethereum DApp with EVM, Remix, GoLang, Truffle, Drizzle and Solidity-Part 1

Recap

If you are new to blockchain technology, reading the below articles in advance is highly recommended:

Note

If you are new to the blockchain technology, taking our Introduction to Blockchain Technology self-paced course is highly recommended. Also, for a comprehensive coverage of blockchain development in Ethereum or mastering Solidity programming, taking our below self paced courses is highly recommended:

Source Codes

Click here to download complete source code for this tutorial.

Outline

For those who are not familiar with blockchain technology reading History and Evolution of Blockchain Technology from Bitcoin article is strongly recommended. Also, if you wish to learn and practice Hyperledger blockchain development, visit Comprehensive Hyperledger Training Tutorials page to get the outline of our Hyperledger tutorial articles.
We have written two sets of tutorials to explore Ethereum and Solidity programming in depth. First set covers the following nine recipes:

  1. Introduction to Ethereum Blockchain Development with DApps and Ethereum VM
  2. Building Auction DApp With Ethereum and Solidity Programming Language
  3. Working with Ethereum Blockchain Applications through Remix IDE
  4. Building Bidding Form in Web3js for Ethereum Auction DApp
  5. Working with web3js API and JSON to Build Ethereum Blockchain Applications
  6. Deployment Environments for Managing Ethereum Smart Contracts
  7. Work with Ethereum Private Network with Golang with Geth
  8. Compiling and Deploying Ethereum Contracts Using Solidity Compiler
  9. Running Ethereum Auction DApp and Solidity Tips

In short, you learn about how to set up and configure Ethereum and develop blockchain applications using Solidity programming language. We explore its key components, including smart contracts and Web3.JS API via an Auction Decentralized Application (DApp) step-by-step.
In second set, we will discuss more advance topics in Ethereum blockchain development and solidity while building a Tontine DApp game step-by-step. Specifically, we cover Truffle and Drizzle. For instance, we show you how a tool such as Truffle can be an assistant in building, testing, debugging, and deploying DApps. In summary, we are going to cover four main topics:

The 2nd set consists of 8 recipes as follows:

    1. Install Truffle and Setup Ganache for Compiling Ethereum Smart Contracts for Tontine DApp Game
    2. Run Tontine Ethereum DApp Game Contract
    3. Design Tontine Ethereum DApp Game Interfaces
    4. Contract Interactions between Ethereum and Solidity via Tontine DApp Game
    5. Work with Truffle Unit Testing in Tontine DApp Game
    6. Debugging with Truffle and Ethereum Remix in Tontine DApp Game
    7. Building Frontend Application for Tontine DApp Game with Drizzle
    8. Running and Playing Tontine Ethereum DApp Game

IMPORTANT: Understanding and completing the first set of recipes are required prior to working on second set of recipes.


Definitive Guide on Ethereum Tools

We gather together a definitive guide to all available tools, components, frameworks, and platforms for developing applications on Ethereum. This is a MUST for all serious Ethereum developers. Visit the below link to read the article and feel free to share it in your network.  
https://myhsts.org/blog/ultimate-guide-to-ethereum-developer-tools.html

 

In this recipe, we introduce the most well-established and mature smart-contract-driven blockchain: Ethereum. It focuses more on enabling developers to build and run distributed applications, Decentralized Apps (DApps), by providing them with built-in tools and currency vehicles.

In this recipe, we start our exploration by building a decentralized auction DApp to sell vehicles on top of the Ethereum blockchain. Along the way, we will introduce you, from a developmental standpoint, to   the tools, concepts, and fundamental basics required to build decentralized applications. This recipe and its follow-up tutorial articles are organized around the following four major topics: i- A general overview of Ethereum, ii- Introducing Solidity (auction smart contract), iii- Introducing web3.js (auction frontend) and iv- The smart contract deployment environment.

 

Introduction to Ethereum

In its first years, the bitcoin system has proven impressive, but it has narrow capabilities. However, the situation changed  after the introduction of the Ethereum blockchain, which, unlike bitcoin, can be extended to much more than just managing a digital currency. In fact, Ethereum is a general-purpose blockchain that is more suited to describing business logic, through advanced scripts, also known as smart contracts. Ethereum was designed with a broader vision, as a decentralized or world computer that attempts to marry the power of the blockchain, as a trust machine, with a Turing-complete contract engine.

Although Ethereum borrows many ideas that were initially introduced by bitcoin, there are many divergences between the two. The following table summarizes the main areas of difference between Ethereum and bitcoin:

Ethereum dapp dev with solidity and truffle


Ethereum Virtual Machine and Smart Contracts

The Ethereum virtual machine and smart contracts are key elements of Ethereum, and constitute its main attraction. The smart contract is a concept that was introduced in the 1990s by Nick Szabo, as a set of commitments specified in digital form. In Ethereum, smart contracts represent a piece of code written in a high-level language (Solidity, LLL, Viper) and stored as bytecode in the blockchain, in order to run reliably in a stack-based virtual machine (Ethereum Virtual Machine), in each node, once invoked. The interactions with smart contract functions happen through transactions on the blockchain network, with their payloads being executed in the Ethereum virtual machine, and the shared blockchain state being updated accordingly. The following diagram provides a general overview of the smart contract execution environment and the interaction between the virtual machine and the blockchain ledger:

 

Ethereum dapp dev with solidity and truffle 


Ether and Gas

Like bitcoin, the Ethereum network has a built-in cryptocurrency, called ether. In addition to operating as a digital currency for payment, ether is used in Ethereum's pricing mechanism for running DApps on the system. Ethereum isn't a free network; you have to pay in ether, whether for transaction fees, or for smart contract deployment or execution. The protocol defines the cost for each computation in a dedicated unit called gas, and the total cost is paid, in order to incentivize miners and avoid denial of service attacks. We will look at the relationship between ether and gas in the next sections.

 

Your first smart contract

Before we go any further, let's be concrete and jump into our first smart contract right away. The following code shows what a standard Hello World smart contract, written in a higher programming language (Solidity), looks like:

pragma solidity ^0.4.24;

contract HelloWorld {
string message = "hello world";
function setMessage(string msg_)       public { message = msg_; }

function getMessage() public view returns (string) { return message; }
}


If you're a developer, this code should be understandable; there is nothing complex. We define a variable, message, with two functions, a setter and a getter. What differs is the fact that we are dealing with a contract that easily stores a given message in Ethereum's blockchain, without using an I/O stream or database connection. We will take a closer look at the meaning of each element later in our next recipe. You can copy , paste, and compile this code by using an online IDE, such as Remix (remix.ethereum.org). You will find further details on handling Remix in the follow-up recipes.

Congratulation! You have created your first Hello World smart contract.

 

What's a DApp?

Have you heard about Web 3.0?

This buzzword is all about a decentralized web, enabled by blockchain networks running DApps, instead of classic client-server web applications. DApp is an abbreviation for decentralized application, and it refers to an unstoppable application running on top of a peer-to-peer blockchain network. The DApp's unstoppability comes from the fact that it eliminates the need for any middlemen to operate, and its execution is replicated across a distributed network.

 

DApp Architecture

Generally, a DApp is a two-tier application, comprised of two main components:

  • A frontend layer on the user side
  • A backend (smart contract) hosted in the blockchain network

 

In the frontend, if you are familiar with Bootstrap or any other framework, you can continue using it. You won't need to manage user accounts, create accounts, or log in to access your DApps, as the network is anonymous, and we only deal with anonymous accounts (addresses), without identification. On Ethereum, the backend operations are ensured by the smart contract, which is validated by the peer-to-peer network. The following diagram shows the layers of a typical DApp and the interactions between the frontend and backend:

Ethereum dapp dev with solidity and truffle

In our next recipe, we build Auction DApp With Ethereum and Solidity Programming Language.

Recap

Ethereum is a general-purpose blockchain that is more suited to describing business logic, through advanced scripts, also known as smart contracts. Ethereum was designed with a broader vision, as a decentralized or world computer that attempts to marry the power of the blockchain, as a trust machine, with a Turing-complete contract engine. Although Ethereum borrows many ideas that were initially introduced by bitcoin, there are many divergences between the two.
The Ethereum virtual machine and smart contracts are key elements of Ethereum, and constitute its main attraction. In Ethereum, smart contracts represent a piece of code written in a high-level language (Solidity, LLL, Viper) and stored as bytecode in the blockchain, in order to run reliably in a stack-based virtual machine (Ethereum Virtual Machine), in each node, once invoked. The interactions with smart contract functions happen through transactions on the blockchain network, with their payloads being executed in the Ethereum virtual machine, and the shared blockchain state being updated accordingly.

Now that you have a basic idea of what Ethereum and DApps are, we can start to build our auction DApp. An auction is a typical example, but it is complex enough to provide a perfect first DApp. It demonstrates the trustless nature of the blockchain, in which we can manage funds automatically and securely, without requiring legal recourse or relying on a trusted third party. Moreover, auctions are generally needed for building smart contracts for token sales in ICOs. In short, our auction DApp will be a web application that enables users to join auctions using ether. Below is high level snapshot of steps we will take in this and follow up recipes:

  • First, we will write (in Solidity) and compile the auction contract
  • We will interact with our contract through a web page
  • We will deploy our smart contract on different environments and set up a local blockchain

 

Auction Application Description

Let's start with the backend layer, represented by the smart contract that manages the auction. We'll consider the following auction design.

A vehicle's owner deploys the contract to the blockchain and becomes the auction owner. The auction is open immediately after the contract deployment, and, once the bidding period is over, the highest bidder wins the auction, and the other participants withdraw their bids. In this example, the bid will be cumulative, which means that if, for example, you bid 100 ETH, and then someone else bids 110 ETH, you can only send an additional 10.000000000000000001 ETH the next time to outbid them; your new bid is the sum of your two bids.

Furthermore, the auction owner can cancel the auction in exceptional cases, and must also be allowed, at the end of the auction, to withdraw the winning bid. The auction interaction

flow is illustrated in the following diagram:

Ethereum dapp dev with solidity and truffle

 

Auction Contract in Solidity

To write our auction contract, we will use Solidity, which is the most popular language used to write smart contracts for the Ethereum blockchain. It's a JavaScript-like language, compiled into bytecode running in the Ethereum virtual machine. If you are familiar with Object-Oriented Programming, learning to write Solidity contracts should be fairly straightforward. Through this auction example, I'll try to lay out the basic and important features of Solidity.

 

Our contract design will be simple. In the first step, we will create an abstract contract, in which we will declare our elementary functions and events. Then, we will use inheritance to create a compliant implementation—a contract with the exact same functions implemented. Abstract contracts help us to decouple the definition of a contract from its implementation, providing better extensibility and code readability.
Start by creating a file called Auction.sol (the .sol extension refers to Solidity files), and paste in the code of our abstract contract, Auction:

 

pragma  solidity ^0.4.24;
  

contract Auction {
address internal auction_owner; uint256 public auction_start; uint256 public auction_end; uint256 public highestBid; address public highestBidder; enum auction_state {
CANCELLED, STARTED
}

struct car {
string     Brand; string     Rnumber;
}

car public Mycar; address[] bidders;
mapping(address => uint) public bids; auction_state public STATE;

modifier an_ongoing_auction() { require(now <= auction_end);
_;
}

modifier only_owner() { require(msg.sender == auction_owner);
_;
}

function bid() public payable returns (bool) {} function withdraw()  public returns (bool) {} function cancel_auction() external returns (bool) {}

event BidEvent(address indexed highestBidder, uint256 highestBid); event WithdrawalEvent(address withdrawer, uint256 amount);
event CanceledEvent(string message, uint256 time);
}

I know this first contract is perhaps enigmatic for you, and maybe it's the first time you have seen a contract of such size (even if it's small). But, don't worry; we will use this first abstract contract as a playground for learning Solidity. In fact, my approach will be to dissect this code line by line and section by section, in order to introduce you to the different major Solidity features.

 

Contract Code Analysis

In Solidity, a contract resembles a class in object-oriented languages, and it defines almost all conventional elements: variables, functions, structures, interfaces, libraries, inheritance, and so on.

The first line—version pragma ^0.4.24;—is a declaration of Solidity's compiler version that your particular code should use. The caret operator (^) indicates that the preceding code will not compile with an earlier compiler, but will compile with both 0.4.24 and any newer version that doesn't introduce any breaking changes.

The second line—contract Auction {...}—declares a contract with the name Auction.

 

State variables

In Solidity, we introduce the concept of states, to express variables (used to store information) declared inside of the contract scope and outside of the function scope, similar to the global variable concept in other programming languages. They represent values that are permanently stored in contract storage (on the blockchain); hence, the contract knows their updated values. In general, a state variable in Solidity is declared as follows:

<Variable type>      <visibility specifier>      <variable name>

In this contract, we'll need to define a set of variables, as follows:

  • auction_owner: This is an address variable that is used to store the vehicle vendor, who is also the auction's owner. This address is where the winning bid goes after the auction ends.
  • auction_end and auction_start: These represent the auction's start and end epoch times, respectively.
  • highestBid: This represents the highest amount bid in ether. highestBidder: This represents the Ethereum address of the highest bidder. bidders: This is an array of all bidder addresses.
  • Bids: This is a mapping, matching the address of each bidder with their total bid.
  • STATE: This represents the auction state, whether it is open or closed (cancelled).

 

Variable State Types

In our code, we used only two basic variable types: uint256 and address

The first represents an unsigned integer of 256 bits. Solidity deals with signed and unsigned integers of various sizes, and to declare an integer, we use one of the keywords, int or uint, for signed and unsigned integers of 8 to 256 bits (uint8 to uint256, in steps of 8).
The type address is a dedicated type that holds a 20-byte value (the size of an address), to represent an Ethereum account's address.

Visibility and Access Modifiers

As you will notice, each variable is preceded by a visibility specifier (public or internal) that defines the accessibility scope. A public state (storage variable) is visible internally and externally (in this case, Solidity creates an implicit public getter for you). An internal variable, however, is only accessible within the current contract or contracts deriving from it, not by external calls, making it similar to the protected keyword in object-oriented programming languages. By default, variables are internal; therefore, the internal keyword can be omitted. In order to access an internal state, we need to define an explicit public getter function. The following is a getter that we define to read the
auction_owner as an internal state (we can define this state as public, and avoid such manipulation):

address internal auction_owner;

function get_owner() view returns(address)  { return auction_owner;
}

Another access modifier, which is unused in our code, is private. This makes the
only variable visible within the contract where it is defined, and not in derived contracts.

Enumerations

As in other programming languages, enumerations help us to define our own data
type that consists of a list of named constants, to ease reading the code. Here, we define an enumeration representing the auction status, with two possible states: CANCELLED or STARTED.
First, we define our enumeration auction_state by using the enum keyword, as follows: enum auction_state { CANCELLED,STARTED }.
Then, we declare a variable of the auction_state type: auction_state public STATE;.
The enum values are converted into integers and numbered in the order that they are defined, starting at zero. If you want to get the value of your declared enum constants, use an explicit conversion uint(STATE). Instead of using the corresponding integer value, you can directly use the enum constants, as follows: auction_state.STARTED (equals 0) or auction_state.CANCELLED (equals 1).

Arrays

Solidity provides three types of data structures: struct, mapping, and arrays.
In our contract, we define a dynamic array to contain all of the bidder addresses. Solidity supports fixed and dynamic sized arrays; therefore, as we don't know the exact number of the bidders a priori, we declare a dynamic array (without fixed length), as follows:

address[] bidders;

An array of a fixed size n and an element type T is declared as T[n], and an array of dynamic size is declared as T[].

Mappings

A mapping is a special dynamic data structure, similar to a hash table, that maps keys to values. A map cannot contain duplicate keys, because a key is hashed and used as a unique index; thus, each key can map to, at most, one value. You can get the value directly by providing a key, without the need to use indices, like in an array:

 

Ethereum dapp dev with solidity and truffle

In Solidity, a mapping is declared as a variable by using the mapping
keyword, mapping(KeyType => ValueType), where KeyType can be almost any type (except for a mapping) and ValueType can actually be any type, including further mappings. In our contract, we're creating a mapping that accepts the bidder's address as the key, and with the value type being the corresponding bid:

mapping(address => uint) public bids;

As with other variables, the mapping can be declared as public, to avoid the need to define a getter for reading its values. Mappings are very useful, as we don't have to manage the indices of the stored elements. For example, to store the bid made by a participant, we
use bids["participant address"] = bid value;.

 

Structures

A structure is a collection of variables of different data types, under a single name. As with most programming languages, we define a structure type by using the struct keyword. In the following example, we declare a structure with two members:

struct car {
string     Brand; string     Rnumber;
}

Here, the struct represents a car by defining its brand and registration number. We then declare a car object by using car public Mycar;.

Functions

After defining the auction states, it's time to define the functions that handle the auction's functionalities. In Solidity, a function has the same meaning as in any other language, and is declared using the keyword function, as follows:
function function_name(<parameter types>)
{internal|external|private|public} [pure|constant|view|payable] [returns (<return types>)]

Like variables, functions can be specified as being external, internal, private, or public, while the default visibility is public. As our first contract, auction, is an abstract contract, we only declare the functions without implementation. They will be implemented later, in a child contract.

Along with the visibility specifier, we can define additional specifiers, such as the following:

  • Constant and view: These play the same role, and both indicate that the function should not modify the state. The constant keyword, however, is deprecated, and doesn't mean that the function returns a constant result.
  • Pure: This is more restrictive, and indicates that the function won't even read the storage state.
  • Payable: This is a keyword that specifies the ability of the function to receive ether.

 

In this contract, we define the following methods, in order to guarantee the basic auction operations:

  • bid(): Enables the participant to send their bids in ether, and accordingly, determines the highest bidder. The bidding in our contract is cumulative, which means that if the bidder is no longer the highest bidder, he can only add an additional amount in the next bid.
  • withdraw(): Enables participants to withdraw their bids once the auction is over.
  • cancel_auction(): Enables the auction owner to cancel the auction he started.
  • destruct_auction(): Destroys the auction contract in the blockchain.

 

Modifiers

One of the most interesting features in Solidity is the function modifiers. They are special control methods that are designated by a special keyword, modifier. Their role is to modify the behavior of defined functions, according to specific conditions. For example, they can automatically check a condition prior to executing the function. Consider the two following modifiers:

modifier an_ongoing_auction() { require(now  <= auction_end);
_;
}

modifier only_owner() { require(msg.sender == auction_owner);
_;
}

The first checks whether the auction is still open, whereas the second restricts the authorization to executing a function to the contract's owner (auction_owner). The usage of the only_owner() modifier makes the contract ownable, which is a common smart contract pattern, thereby giving the contract owner specific privileges, similar to an admin in other systems. Generally, in modifiers, we check conditions by using the require, revert, or assert functions. The underscore in the modifier's body will be substituted by the code of the function being modified.

 

Condition and Error Verification

Solidity initially used the special keyword throw to stop and exit the contract execution when called. Since then, the functions assert(), require(), and revert() have been introduced (in Solidity 0.4.10), in order to enhance the error handling. Although the throw function is now being deprecated, you are still able to use it.

With all of these functions in place, we can use them equivalently, as follows:
Ethereum dapp dev with solidity and truffle

                                                                         
You might have noticed that we have reversed the required conditional statement between, on the one hand, require() and assert(), and on the other hand, throw and revert(). In assert() and require(), we provide the statement that we want to be true,
whereas throw and revert() behave like exit functions that you call when your condition isn't met.

The differences between these functions can be described as follows:

  • assert(bool condition): Throws if the condition is not met; this is to be used for internal errors. It uses up all remaining gas and reverts all changes.
  • require(bool condition): Throws if the condition is not met; this is to be used for errors in input or external components. Generously, it will refund the remaining gas to the caller.
  • revert(): Aborts execution and reverts state changes with a gas refund.
  • throw: Throws and consumes any remaining gas.

 

As revert() and require() both refund the unconsumed gas, they should be used to ensure valid conditions, whereas assert() should be used to check a harmful statement and to protect your contract, meaning that you can use assert to avoid overflow or underflow. Think of assert() as a handbrake that you use when something very wrong has happened, and the other functions as normal brakes.

An important feature that has been introduced in a newer Solidity version (0.4.22) is that you can return an argument to specify the error reason in your assert or require function:

require(msg.sender == owner, "the execution is reserved to the contract's owner");

if (msg.sender != owner) {
revert("the execution is reserved to the contract's owner");
}

 

Events

Events allow for the convenient use of the EVM logging facilities. They are an important concept in smart contracts, as any off-chain environment connected to Ethereum's JSON- RPC API can listen to these events and act accordingly.

In general, there are three main use cases for events and logs in DApps:

  • To return values from a smart contract to a user interface
  • To provide asynchronous triggers with indicative data that we can listen for in the frontend
  • As a cheaper form of storage in the blockchain

 

When they are called, they cause their arguments to be stored in the transaction's log. An event is declared as using the event keyword, as follows: event CanceledEvent(string message, uint256 time);.
In the declaration, we determine the parameter types that we expect to include in the log. In our case, the previously created event CanceledEvent will be emitted once the auction is cancelled and will broadcast a message, Auction has been cancelled, with the time of cancellation. We also defined two other events:

  • BidEvent(): Informs us of a newly registered bid and provides us with the bidder's address and the bid
  • WithdrawalEvent(): Logs the withdrawal operations, giving the withdrawer's address and the withdrawal amount

 

As you'll see later when developing the web interface, it is possible to filter for specific values of indexed arguments (using the indexed keyword) in the user interface using the filtering functionality of Web 3.0.

So far, we have covered the basic programming constructs (such as variables, data types, and data structure) and introduced the important concept of a contract by defining an abstract contract representing auctions in general. Now, let's move forward and define our main derived contract.

 

Inheritance

Solidity supports advanced features, such as multiple inheritance, including  polymorphism. After writing our abstract class, let's extend our code by writing our second contract (child contract), called MyAuction, in the same contract file. It will inherit from the first contract and implement the defined auction functions.

The following is how you declare a derived contract inheriting from our first contract: contract MyAuction is Auction {..}.

The keyword is indicates to the compiler that MyAuction is derived from
the Auction contract. Hence, the MyAuction contract can access all members, including private functions and storage variables in the Auction contract.

Hint: Instead of defining both contracts in the same Solidity file, you can define the parent in a separate file and import it by using the directive import "filename";.

 

Constructors

As with Object-Oriented Programming (OOP), you can define a constructor for your contract. It's a special function using the same name as the contract it belongs to. Unlike in OOP, a contract's constructor is invoked once and only once during the first deployment to the blockchain, and usually defines the initial contract behavior.

In the MyAuction contract, our constructor is extremely simple:

    function MyAuction (uint _biddingTime, address  _owner,string _brand,string
_Rnumber) public { auction_owner = _owner; auction_start = now;
auction_end = auction_start + _biddingTime* 1 hours; STATE = auction_state.STARTED;
Mycar.Brand = _brand; Mycar.Rnumber = _Rnumber;
}

This constructor, upon creation, sets the relevant states by defining the auction owner, the auction opening and ending date, and the car's details. Consequently, our auction starts immediately, once the contract is deployed. In newer Solidity versions (from the compiler version 0.4.22), you can declare a constructor by using the constructor keyword:
constructor(uint _biddingTime, address _owner,string _brand,string
_Rnumber) public {/*code*/}

 

Time in Solidity

As you will notice, in the constructor, we used the keyword now to set the auction start time, whereas the auction's end is calculated by adding to the auction start time a number of hours defined by the _biddingTime argument.

The now keyword is an integer variable that returns the block's timestamp (it's an alias for the special global variable block.timestamp), in which the contract was embedded.
Solidity also provides us with some helpful time units (seconds, minutes, hours, days, weeks, and years) that can be applied to a variable as a suffix, to automatically convert a unit to the equivalent time, in seconds. In your constructor, the elapsed number of hours (_biddingTime * 1 hours) is automatically converted to seconds and added to the Linux epoch time provided by the now variable.
We could, alternatively, manage the auction duration by using block numbers instead of the time epoch. In that case, the auction will start once a specific block is mined and stop at a specific future block. For that, you'll use the special variable block.number provided by Solidity, which gives you the current block's number.

 

Special Variables and Functions

Earlier, we introduced two special system variables: block.timestamp and block.number. Solidity provides us with a set of global variables and special functions that exist in the global namespace and that are mainly used to provide information about blocks and transactions.

The following is a list from the official documentation:

  • block.blockhash(uint blockNumber): Returns a hash of the given block (bytes32)—only works for the 256 most recent blocks, excluding the current block
  • block.coinbase (address): Provides the current block miner's address
  • block.difficulty (uint): Represents the current block difficulty
  • block.gaslimit (uint): Represents the current block gas limit
  • block.number (uint): Represents the current block number
  • block.timestamp (uint): Represents the current block timestamp, as seconds since Unix epoch
  • gasleft() (uint256): Returns the remaining gas
  • msg.data (bytes): Represents a copy of calldata
  • msg.sender (address): Represents the address of the sender of the message (current call)
  • msg.sig (bytes4): Represents the first four bytes of calldata (that is, function identifier)
  • msg.value (uint): Represents the number of wei sent with the message
  • tx.gasprice (uint): Represents the gas price of the transaction
  • tx.origin (address): Represents the sender of the transaction

 

The values of all attributes of the msg object, including msg.sender and msg.value, vary for every external function call according to the sender and the amount carried by the transaction. In our constructor, we can provide the auction owner as an argument,
using msg.sender to directly set the sender of the deployment transaction as the owner:
auction_owner = msg.sender;.

 

The Fallback Function

In Solidity, there is another special method, which is the fallback function. It's an unnamed function that cannot have arguments, nor return anything, and it is declared as follows: function () public payable { }.
The fallback function is executed if the contract is called and no function in the contract matches the specified function's signature. This is not a mandatory function to declare, but you can include it, in order to define your contract's behavior when it receives transactions without data. To accepts funds, you have to declare it as payable.

 

Function Overloading

At this level, we need to overload the functions in the child contract, MyAuction, that we defined earlier in the abstract contract, Auction. In order to achieve that goal, we need to keep the same name and declaration (the same visibility and return type) as in the Auction contract and then define the function's body. You'll overload the function in the sequence in which they were defined in the abstract contract, as follows.

The Bidding Function

Let's start by defining the bidding function, which will allow participants to place bids in ether (wei):

function bid() public payable  an_ongoing_auction returns (bool){ require(bids[msg.sender] + msg.value >  highestBid, "can't bid, Make a
higher Bid");

highestBidder = msg.sender; highestBid = msg.value; bidders.push(msg.sender);
bids[msg.sender] = bids[msg.sender] + msg.value; emit BidEvent(highestBidder, highestBid);
return true;
}

Nothing is different from the original declaration; we only add a modifier at the end of the function declaration, to enable its execution only during the auction period; otherwise, an exception will be raised. As I have stated repeatedly, the payable keyword enables the function to receive ether carried by the bidding transactions.

In the body of the bid() function, we initially check whether the total of the bids sent by a participant is higher than the highest bid, using require(bids[msg.sender] + msg.value > highestBid);.
Depending on how much ether the bidder sends, either they will be the new highest bidder or their bid will be refused. If the bid was successful, the contract will fire the BidEvent event, to announce the new highest bid and bidder. In the newer Solidity versions, you can use the emit keyword to fire an event.
Before emitting the event, we add the bidder's address to the array of participants, using the push function. Afterwards, we update the participant's bid in our mapping bids: bids[msg.sender] = bids[msg.sender] + msg.value;.
At the end, this function returns true to indicate a successful execution (bidding). We will use this return pattern in all other functions.

Canceling an Auction

Wouldn't it be logical to enable the auction owner to cancel the auction?

Such a function should be executed exclusively by the auction owner, while the auction is still open; thus, we use the modifiers only_owner and an_ongoing_auction:

    function cancel_auction() only_owner  an_ongoing_auction returns (bool) { STATE = auction_state.CANCELLED;
CanceledEvent("Auction Cancelled", now); return true;
}

This function will change the state of the auction status to Cancelled, using the enum value auction_state.CANCELLED we defined earlier, and the event CanceledEvent will be fired announcing the auction cancellation.

Withdrawing Bids

After the auction ends, you'll need to enable bidders to get their ether back. For security reasons, it's better to adopt a withdrawal pattern —this helps us to avoid security issues that could cause funds to be lost:

    function  withdraw() public returns (bool){
require(now > auction_end , "can't withdraw, Auction is still open"); uint amount = bids[msg.sender];
bids[msg.sender] = 0; msg.sender.transfer(amount); WithdrawalEvent(msg.sender, amount); return true;
}    

There is nothing new here except, as you might have noticed, the use of a new function, transfer(). Along with another function, send(), both methods enable the contract to send funds to a designated address (msg.sender). In this case, the contract sends the corresponding bid amount back to the withdrawal requester's address.
Notice that we're following the recommended pattern for functions that send

  • ETH: Check preconditions
  • Send ether and throw if the send fails (roll back method execution)
  • Emit a log event and return true

You might be wondering why we don't just define a function that automatically refunds all participants once the auction is over, a function similar to the following:

function payback_participants() internal  returns (bool){ uint256 payback = 0;
for (uint256 i = 0; i < bidders.length; i++)
{
if (bids[bidders[i]] > 0) { payback = bids[bidders[i]]; bids[bidders[i]] = 0; bidders[i].transfer(payback);
}
}
return true;
}

Well, it's a risky anti-pattern. You should know that send or transfer methods can actually fail (for different reasons) and therefore, the payment loop won't end by successfully paying back all of the participants. For example, a malicious user that bid only 1 wei from a contract with a non-payable fallback can block the refund process by making the transfer method fail (and therefore throw) forever, meaning that the loop will never get executed completely.

 

Contract Destruction

What about introducing a nuclear launch button in our contract that, once pushed by the auction owner, will make the contract disappear from the blockchain? The contract destruction will be ensured by the destruct_auction() method, which can be invoked if all participants have withdrawn their bids, as follows:

function destruct_auction() external  only_owner returns (bool) { require(now > auction_end, "You can't  destruct the contract,The auction
is still open");
for (uint i = 0; i < bidders.length; i++)
{
assert(bids[bidders[i]] == 0);
}
selfdestruct(auction_owner); return true;
}

The first thing that we can see here is that Solidity defines for-loops like standard languages, and you can access the length of a dynamic size array by using
the .length member.
More importantly, Solidity defines a special function, selfdestruct(address), to destroy the current contract (it will no longer be accessible) and send all its funds to the address given as the argument. This is a space- and cost-saving feature as, when you are finished with a contract, it will cost you far less gas using selfdestruct than just sending the contract funds using address.transfer(this.balance).
But wait! Isn't the blockchain immutable?


The answer needs a little dive into the Ethereum block structure, which is out of the scope of this recipe. However, it's worth noting that the selfdestruct method clears all the contract's data, and frees up space from the current and future state tree (the mapping between the contract's account and its states), but not from the previous blocks. The contract bytecode will remain in an old block but its account will no longer be accessible in the state tree; therefore, the data is still immutable. In other words, after calling selfdestruct, the state tree will be updated without the destroyed contract states.

 

All set! We have finished our auction smart contract. Now let's enjoy compiling and running our first achievement in the next recipe.

 

Recap

As we will discuss in our follow up recipes, different tools and options are available to compile and deploy smart contracts. But at this level, we don't want to waste time in setting up complicated tools, or our environment. Thankfully, the Ethereum project provides us with the Remix web browser IDE (also known as Browser-Solidity), which is an online IDE that can be used to compile, deploy, and invoke smart contracts.

Let's make our way over to Remix by visiting https://remix.ethereum.org, then paste the complete contract code into a new contract file.

Ethereum dapp with truffle and solidity

After pasting the code into Remix, you can compile it by pressing the Start to compile button:

Ethereum dapp with truffle and solidity


You might get some warnings (sometimes irrelevant), but if it compiles without any errors, you can visualize the result of the compilation process by pressing the Details button.
Among other things, you'll get a list of contract details, ranging from metadata and bytecode to ABI, and even our contract's web3.js deployment code. There is an auto- compile option, which if checked will make Remix recompile the contract each time you edit the code.

 

On the upper-right side of our screen, we have several tabs. The Settings, Debugger, Analysis, and Support tabs all have their use cases and are worth exploring. We're going to be using the Run tab. When you select it, you'll see a few different contract settings that we need to define, as shown here:
Ethereum dapp with truffle and solidity


Under the Run tab, you'll have a panel of two forms. The first helps you to define the following settings:

  • Environment: Represents the deployment environment to which you want to connect Remix. At this level, you'll choose the JavaScript VM option to simulate an EVM in your browser.
  • Account: A set of virtual accounts that generated and funded with 100 virtual ether each.
  • Gas limit: Specifies the maximum gas you are willing to pay for the transaction (leave it unchanged).
  • Value: Represents the amount of ether that you are willing to send in your transaction (leave it at zero for the deployment).

The second form is dedicated to deploying the contract. The first element is a drop-down list to select which contract you want to deploy, in case you have multiple declared contracts in your file code. In our case, we have to select the child contract (MyAuction) not the main contract (Auction). Just below ,you have the Deploy button to deploy your contract and a text input to provide the constructor's arguments (comma-separated). In our case, we will need to provide the auction duration time in hours, the address of the  auction's owner, and the car's brand and registration number, for example:

1,"0xca35b7d915458ef540ade6068dfe2f44e8fa733c","ferrari","IS2012"

 

The last thing to mention is that if you want to interact with an already deployed contract, you can use the At Address button by providing the contract's address.


Once the deployment is successful, you'll get a form representing your contract methods and states' as shown here:

Ethereum dapp with truffle and solidity

In contrast to the red button, the blue one means that you can read a variable or execute a function without initiating a transaction as it represents public variables, and pure or view functions. Therefore, the constructor is executed and the auction is opened and lives at a virtual address in the memory.


Finally, let's bid. To execute the bid() function, enter in the value field in the transaction section the amount of your bid in a specific ether unit, then press the red bid button. To simulate multiple bidders, you can bid using a different virtual account each time. Once the function is executed, you'll get information about the status and result of your bid action, displayed in Remix's log panel. If you click on the Details button, it will provide you with further details, as follows:

Ethereum dapp with truffle and solidity

Notice there are the transaction cost and execution cost, which represent an estimation of the execution fee that senders of transactions (in our case, the bidder) will pay for bidding; they can be defined as follows:

  • Transaction cost: This is the cost (in units of gas) of sending the transaction, which depends on the data size that it's carrying (function call and parameters) Execution cost: This is the cost (in units of gas) of the computational operations
  • which are executed as a result of the transaction instructions

 

If everything is fine (no out-of-gas or any other kind of error), you can start creating the frontend side—a bidding form which is covered in our next recipe.


Recap

After a first validation of the auction contract using Remix in our previous recipe, it's time to move to the frontend and build a simple web interface that allows participants to interact with the auction. Ethereum is JavaScript-friendly, so you can build your DApp's interfaces using whatever JavaScript framework you prefer: JQuery, ReactJS, or AngularJS.

First off, create a new folder called DAPP/, inside of which you create two files: index.html and auction.js.
In the HTML file, we'll create a bidding form and a display board. The following is the HTML code:

<html>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css ">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"><
/script>
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script

<script src="./auction.js"></script>
</head>

<body onload="init()">
<div class="col-lg-12">
<div class="page-header">
<h3>Car Auction Dapp</h3>
</div>
<div class="col-lg-6">
<div class="well">
<div>
<legend class="lead">Car Details</legend>
<label class="lead"> Brand: </label>
<text id='car_brand'></text>
<br>
<label class="lead">Registration Number: </label>
<text id='registration_number'></text>
</div>
<legend class="lead">Bid value</legend>
<small>eg. 100</small>
<div class="form-group">
<input class="form-control" type="text" id="value" value="10"
></input>
<text id="valueValidation"></text>
</div>
<div>
<button class="btn btn-default" id="transfer" type="button" onClick="bid()">Bid!</button>
<br>
<text id="biding_status"></text>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="well">
<div>
<legend class="lead">Auction Details</legend>
</div>
<div>
<ul id='transfers'>
<li>
<label class="lead">Auction End: </label>
<text id="auction_end"></text>
</li>
<li>
<label class="lead">Auction Highest Bid: </label>
<text id="HighestBid"></text>
</li>
<li>
<label class="lead">My Bid: </label>
<text id="MyBid"></text>
</li>
<li>
<label class="lead">Auction Highest Bider: </label>
<text id="HighestBidder"></text>
</li>
<li>
<label class="lead">Auction Status: </label>
<text id="STATE"></text>
</li>
</ul>
</div>
<br>
<div>
<legend class="lead">Events Logs </legend>
<text id="eventslog"></text>
</div>
</div>
</div>
</div>
<div class="col-lg-6" id="auction_owner_operations">
<div class="well">
<div>
<legend class="lead">Auction Operations</legend>
<button class="btn btn-default" id="transfer" type="button" onClick="cancel_auction()">Cancel auction!</button>
<button class="btn btn-default" id="transfer" type="button" onClick="Destruct_auction()">Destruct auction!</button>
</div>
</div>
</div>
</body>

</html>

I assume you are familiar with HTML; therefore I'll avoid explaining what all these tags mean. In the preceding code, we have introduced four JavaScript functions, namely bid(), init(), destruct_auction(), and cancel_auction (), which need to be defined in the separate auction.js file, in order to represent the basic auction operations.
The other important part is the line importing the Web3Js library:

    <script  src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js">
    </script> 

In our next recipe, we will discuss Web3.JS API and advance Solidity features in depth.

 

Recap

 

Ethereum provides us with web3.js, which is a useful API to make the web developer's life easier. This JavaScript API enables us to communicate with an Ethereum node using JSON RPC endpoints exposed on top of HTTP, WebSocket, and/or IPC transports from a web page.

In auction.js, copy and paste the following code, so we can walk through it step by step while introducing the main web3.js features:

var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545")); var bidder = web3.eth.accounts[0];
web3.eth.defaultAccount = bidder;
var auctionContract = web3.eth.contract("Here the contract's ABI"); // ABI omitted to make the code concise

function bid() {
var mybid = document.getElementById('value').value;

auction.bid({
value: web3.toWei(mybid, "ether"), gas: 200000
}, function(error, result) { if (error) {
console.log("error is " + error); document.getElementById("biding_status").innerHTML = "Think to
bidding higher";
} else {
document.getElementById("biding_status").innerHTML = "Successfull bid, transaction ID" + result;
}
});
}

function init() { auction.auction_end(function(error, result) {
document.getElementById("auction_end").innerHTML = result;
});
auction.highestBidder(function(error, result) { document.getElementById("HighestBidder").innerHTML = result;
});
auction.highestBid(function(error, result) {
var bidEther = web3.fromWei(result, 'ether'); document.getElementById("HighestBid").innerHTML = bidEther;
});
auction.STATE(function(error, result) { document.getElementById("STATE").innerHTML = result;
});
auction.Mycar(function(error, result) { document.getElementById("car_brand").innerHTML = result[0]; document.getElementById("registration_number").innerHTML =
result[1];
});
auction.bids(bidder, function(error, result) { var bidEther = web3.fromWei(result, 'ether');
document.getElementById("MyBid").innerHTML = bidEther; console.log(bidder);
});
}

var auction_owner = null; auction.get_owner(function(error, result) {
if (!error) {
auction_owner = result;
if (bidder != auction_owner) {
$("#auction_owner_operations").hide();
}
}
});

function cancel_auction() { auction.cancel_auction(function(error, result) {
console.log(result);
});
}

function Destruct_auction() { auction.destruct_auction(function(error, result) {
console.log(result);
});
}

var BidEvent = auction.BidEvent(); BidEvent.watch(function(error, result) {
if (!error) {
$("#eventslog").html(result.args.highestBidder + ' has bidden(' + result.args.highestBid + ' wei)');
} else {
console.log(error);
}
});

var CanceledEvent = auction.CanceledEvent(); CanceledEvent.watch(function(error, result) {
if (!error) {
$("#eventslog").html(result.args.message + ' at ' + result.args.time);
}
});

const filter = web3.eth.filter({ fromBlock: 0,
toBlock: 'latest', address: contractAddress,
topics: [web3.sha3('BidEvent(address,uint256)')]
});

filter.get((error, result) => {
if (!error) console.log(result);
});

Step 1 – talking to the blockchain

Web3Js provides the web3 object that enables us to exploit the Web3 API functions in JavaScript. Therefore, the first action to take is to instantiate a web3 object as follows: var web3 = new Web3();

This object needs to be connected to an RPC provider to communicate with the blockchain. We set a local or remote web3 provider using web3.setProvider(new web3.providers.HttpProvider("http://RPC_IP:RPC_Port"));, where RPC_IP is the RPC provider's IP and RPC_Port is its RPC port.

Step 2 – interaction with the smart contract

Web3 also provides a JavaScript object, web3.eth.Contract, which represents your deployed contract. To find and interact with your newly deployed contract on the blockchain, this object needs to know the contract's address and its application binary interface (ABI):

var auctionContract = web3.eth.contract(“your contract's ABI”); var auction = auctionContract.at(“contract address”);

The ABI

For many, the ABI is a slightly confusing concept. The ABI is essentially a JSON object containing a detailed description (using a special data-encoding scheme) of the functions and their arguments, which describes how to call them in the bytecode.

Based on the ABI, the web3.js will convert all calls into low-level calls over RPC that the EVM can understand. In other words, web3.js needs to know some information (in a predefined format) about the functions and variables, in order to generate instructions that can be interpreted by an Ethereum node (EVM), and to get you the result back in a human- readable way. The EVM doesn't know about function names or variables, it processes only the data as a sequence of bytes accordingly to predefined rules. For example, the first four bytes in a transaction payload specify the signature of the called function, hence the need for an ABI that helps any API or tool to generate a transaction with correct low-level payloads and to read returned values by the contract.

Call versus send transactions

In our JavaScript script, we define the following functions previously called in the HTML file:

  • init(): Serves to read contract states and display auction details such as the current highest bid and bidder, the auction status and more
  • bid(): Enables participants to make a bid
  • cancel_auction(): Enables the owner to cancel the auction
  • destruct_auction(): Destroys the contract

Each of these functions invokes methods defined in your contract. In Ethereum, there are two ways to invoke a method present in a smart contract, whether by addressing a function call or by sending a transaction.

Invoking contract methods via a call

A call is a contract instance invocation that doesn't change the contract state, and includes calling view or pure functions or reading public states. The call only runs on the EVM of your local node and saves you the expensive gas as there is no need for broadcasting the transaction. In your init() function, we need exactly that, as we only have to read the contract states. We can call a method foo() on the local blockchain without having to send out a transaction using myContractInstance.foo.call(arg1,arg2...).

Invoking contract methods via a transaction

To change the state of the contract instance, instead of making a call, you need to send a transaction that costs you real money (gas) to validate your action.

For instance, to invoke the bid() method, you have to send a transaction to the blockchain network with the necessary arguments and fees. Just like with the call, to invoke the foo() method, you need to explicitly make the invocation using sendTransaction() as follows:
myContractInstance.foo.sendTransaction(param1 [, param2, ...] [, transactionObject] [, callback]);
Web3.js is smart enough to automatically determine the use of call or sendTransaction based on the method type indicated in the ABI, therefore you can directly use the following:

auction.bid({value: web3.toWei(mybid, "ether"), gas: 200000}, function(error, result){...});

In general, to execute a function foo(argument1, argument2), we use the following:
auction.foo(argument1, argument2,{Transaction object}, fallback_function{...});
Here, auction is a web3.js contract object. In the invocation, we provide the following arguments in the following order:

  • The contract's function arguments.
  • A transaction object that represents details of the transaction that will execute the function (source, destination, amount of ether, gas, gas price, data). As the address for the sending account, we use the coinbase that is the default account that the Ethereum client will use. You can have as many accounts as you want and set one of them as a coinbase.
  • At the end, we define a callback function which will be executed once the transaction is validated.

 

In your bid() function, the bid amount is specified in the transaction object, while in the UI form, the bidder will specify the amount in ether, therefore we will need to convert the bid into wei by using web3.toWei(mybid, "ether").

Callbacks

Web3.js is designed to work with a local RPC node, and all of its functions use synchronous HTTP requests by default. If you want to make an asynchronous request, you can pass an optional callback as the last parameter to most functions. All callbacks us an error-first callback pattern, as follows:

web3.eth.foo(argument1,..,argumentn,  function(error, result) { if (!error) {
console.log(result);
}
});

Reading state variables

As reading the public state doesn't change any information in the blockchain, it can be performed locally using a call. For example, to read the auction's highestbid variable, you can use auction.highestBid.call();.

Watching events

One more important thing to take care of in your frontend is handling events. Your DApp should be able to listen for fired events by applying the function watch() to the expected event to detect changes, or get() to read a specific log. The following code shows an example of event watching:

var CanceledEvent = auction.CanceledEvent(); CanceledEvent.watch(function(error,  result) {
if (!error) {
$("#eventslog").html(result.args.message + ' at ' + result.args.time);
}
});

Each time a new bid is received by the contract, the callback function will display the log.

Indexing events and filtering

In our auction smart contract, we used the indexed argument in BidEvent() declaration for a clever reason:
event BidEvent(address indexed highestBidder, uint256 highestBid);

When you use the indexed keyword in your event, your Ethereum node will internally index arguments to build on indexable search log, making it searchable, meaning you can easily perform a lookup by value later on.

Suppose that the event was emitted by the MyAuction contract with the arguments BidEvent(26, “bidder's address”);. In this case, a low-level EVM log with multiple entries will be generated with two topics and a data field as shown in the following browser console screenshot:


Ethereum dapp with truffle and solidity

The topics and data fields are as follows:


Topics:

The event signature: The large hex number 0d993d4f8a84158f5329713d6d13ef54e77b325040c887c8b3e5
65cfd0cd3e21 is equal to the Keccak-256 hash of BidEvent (address, uint256)

 

Data:

HighestBidder: The bidder's address, ABI-encoded and ighest bid value, ABI-encoded

As you know, logs tend to be much larger and sometimes longer. In web3.js, you can filter data in your contract's log by simply applying a filter as follows:

    var contractAddress="0x00..."
const filter = web3.eth.filter({fromBlock: 1000000,toBlock: 'latest',address: contractAddress,topics: [web3.sha3('BidEvent(address, uint256)')]})
filter.get((error, result) => { if (!error) {
console.log(result);
}
});

The preceding filter will give you all the log entries for the BidEvent event corresponding to your filtering object, in which we define the blocks (fromBlock, toBlock) to read the log from, along with the account address and the event we are interested in. To listen for state changes that fit the previous filter and call a callback, you can use the watch method instead, as follows:

filter.watch(function(error, result) { if  (!error) {
console.log(result);
}
});

To stop and uninstall the filter, you can use the stopWatching
method: filter.stopWatching();
As shown in the preceding screenshot, the log outputs are ABI-encoded, and to decode a log receipt, you can use decodeParameter available in web3Js 1.0 as follows:

    web3.eth.abi.decodeParameter(‘uint256',  '0000000000000000000000001829d79cce6aa43d13e67216b355e81a7fffb220')

Alternatively, you can use an external library such as github.com/ConsenSys/abi-decoder .

 

Numbers in Ethereum and floating point

You might be surprised to learn that the Ethereum VM doesn't support floating point numbers. Discussing the reasons behind that choice is out of the scope of this book, so let's focus on how to deal with this limitation, in order to enable bidding in floating point numbers.

In Ethereum, we can overcome this issue by using the system used to represent different units of ether. In this system, the smallest denomination or base unit of ether is called wei (Ether=1018 wei) along with other units:

  • 109 wei = 1 Shannon
  • 1012 wei = 1 Szabo
  • 1015  wei = 1 Finney

Although we did not set the units of any bids in the contract, the received bids will be counted in wei. This will help us to accept floating point numbers, as they will become integers after being multiplied by 1018. For instance, 1234.56789 ether will be represented as 123456789E+14 wei. While the bid is done through the auction form in ether and stored in the contract in wei, to display back the bid's value in ether, we convert from wei to ether using var value = web3.fromWei('21000000000000', ‘ether');.

Transaction status receipt

Since the Byzantium Fork, it's been possible to find out whether a transaction was successful. Indeed, you can check the transaction status using the following:

var receipt = web3.eth.getTransactionReceipt(transaction_hash_from_60_minutes_ago);

It returns a set of information including a status field, which has a value of zero when a transaction has failed and 1(0x1) when the transaction has succeeded (it has been mined).

 

So far, we have tested our contract and our user interface is ready to interact with it. We now have to assemble the puzzle pieces. To get our DApp working, we need to deploy our contract in a test environment other than Remix's VM JavaScript that we used earlier. We explain it in details on our next recipe.

Recap

In Ethereum, we have multiple ways to deploy a smart contract without spending real ether. In this recipe, we will present how to set up and deploy your contract in the following testing environments:

 

Option 1 – Ganache

If you're looking for a testing blockchain with a graphical
interface, Ganache (previously TestRpc) is for you. It's an in-memory blockchain (think of it as a blockchain simulator) that runs locally.

Download and install it from the official Ganache repository (https://github.com/trufflesuite/ganache/releases) for the appropriate version for your OS.
When you run Ganache, you will get a graphical screen showing some details about the server, the blocks created, transactions, and a list of created accounts, each loaded with 100 ether:

Ethereum dapp with solidity and truffle

To interact with Ganache, you can use Remix, but this time, you have to specify a new web3 provider with Ganache's IP and RPC port; for example, http://localhost:7545 (if you have connection troubles, try to use Remix over HTTP, not HTTPS):

Ethereum dapp with solidity and truffle


Once Remix is connected to Ganache, deploy your smart contract as you did earlier and start bidding through Remix. In Ganache's interface, you'll be able to visualize the transactions and the created blocks:

Ethereum dapp with solidity and truffle

If you think Ganache is enough for you, you can stop here and jump directly to the Running the auction DApp section, in order to run the auction DApp using Ganache. However, if you're interested in learning about other possible deployment environments so you can choose the suitable one for you, continue reading.

 

Option 2 – Testnet

Similar to bitcoin, Ethereum's Testnet is a public network dedicated to testing developers' contracts online without using real ether. You can join this network without the need to run a full node, by using a plugin called MetaMask on your browser. Let's see how it's possible.


Connecting MetaMask to Testnet

MetaMask is a browser plugin that allows your normal browser to behave as a web3 browser, to interact with DApps, and to send transactions without running an Ethereum node. MetaMask achieves this by injecting the web3js API into every web page's JavaScript context.

The necessary instructions for installing and setting up MetaMask are well documented on their official website, at: https://metamask.io. After the process of wallet creation, switch to the Ropsten test network in MetaMask's settings by clicking on the network selector located on the upper left corner. Once you're connected to Ropsten, you'll need to get some free worthless ether by choosing to buy some coins as shown in the following screenshot:
Ethereum dapp with solidity and truffle

MetaMask can be connected to any RPC provider locally (Ganache, Geth) or online (testnet, Mainnet). For a detailed step-by-step guide to using MetaMask, I point you to the official documentation available at https://github.com/MetaMask/faq/blob/master/USERS.md.


All set; now, go back to your Remix browser (you may need to refresh it) and select (in Remix) injected web3 as the environment option, in order to deploy your contract directly online. MetaMask will initiate the deployment transaction and give you back the contract address:

Ethereum dapp with solidity and truffle


MetaMask provides an Ethereum Etherscan link for each transaction, in order to visualize, among other details, the transaction status and gas cost:

Ethereum dapp with solidity and truffle

The contract is easily deployed in the testnet.

Alternatively, you can connect Remix to the testnet by setting up a light node connected to the testnet network as explained in the next section. To test your auction web page using MetaMask, you have to add the following code snippet to the beginning of your auction.js file to detect MetaMask's injected web3 instance:

    if  (typeof web3 !== 'undefined') { App.web3Provider = web3.currentProvider; web3 =  new Web3(web3.currentProvider);
} else {
// change to your RPC provider IP and Port App.web3Provider = new
web3.providers.HttpProvider('http://127.0.0.1:7545'); web3 = new Web3(App.web3Provider);
}

Instead using only web3.setProvider(new web3.providers.HttpProvider("http://127.0.0.1:8545")); as we did earlier in section talking to the blockchain.

The testnet network is very helpful as it gives you an accurate idea of the delay processing and cost of your transactions. However, the implied delay time and limited ether won't be helpful for developers who regularly change their DApp's code, hence the following third option or Ganache is more suitable as a starting environment. You can then you move to this testnet option before going into production on the Mainnet.

 

Option 3 – private network

Despite the ease of using the previous environment, which abstracts away all the details, it is still good to know how things work at a granular level. Besides, you might face the need to deploy private Ethereum blockchains for private entities to use in production, or during the software development process.

Let's set up our private Ethereum network (a kind of localhost), composed of two running nodes on the same machine which is covered in our next recipe.

 

Geth

Recap


To start, you wil need to install an Ethereum client, for example Geth (Golang Ethereum client). You'll find the instructions to install Geth for your operating system on the Ethereum repository on GitHub (https://github.com/ethereum/go-ethereum/wiki/ Installing-Geth). For Ubuntu, you can install the Geth client using the following command:

sudo add-apt-repository -y  ppa:ethereum/ethereum sudo apt-get update
sudo apt-get install ethereum

For this local network, we will be running two nodes (on the same machine), therefore we need to create two different folders to host their blockchain copies and wallets. Create a directory called Mytestnet with the following two subdirectories:

    ~/Mytestnet
|-- nodeA
|-- nodeB

 

Creating new accounts

We will create new accounts for our new network. Note that an account is not tied to any specific chain, it's just a private/public key pair.

Change directory to the newly created folder Mytestnet and run the following commands:

geth account new --datadir nodeA geth  account new --datadir nodeB/pre>
  

Repeat the same command to get different accounts on both nodes that we will use to interact with the contract as bidders. Geth will print out the address for each user, so think of saving these addresses in a file, in order to use them later.

You can list the created account for node A or B by using

geth account list -- datadir                        nodeA/nodeB: 

Ethereum dapp with solidity and truffle

 

Genesis file

As you know, each blockchain starts with a genesis block and keeps building on top of it. Therefore, before running your private network, you first have to prepare your own genesis block by defining a genesis file.

You can easily create new genesis files with a command-line tool called puppeth, which is a private blockchain manager that comes as a utility with Ggeth. Run puppeth and follow the configuration wizard. You'll need to answer a few questions as shown in the following screenshot:

Ethereum dapp with solidity and truffle


When it asks you about accounts to pre-fund, give it the addresses that were created earlier. At the end of the process, save the genesis file as a JSON file, genesis.json:

Ethereum dapp with solidity and truffle

 

Node initialization

Now that we have the genesis.json file, let's forge the genesis block. Both nodes should initialize their chain using the same genesis file by running the following commands:

geth --datadir nodeA init genesis.json geth --datadir nodeB init genesis.json

All set. Now you can start your new chain on both nodes using two Terminals. Starting node A as follows:

geth --datadir nodeA --networkid 1234 --rpc   --rpcport 8545 --port 8888   -- rpcapi “db,eth,net,web3,personal,miner,admin”--cache=128 --rpcaddr 0.0.0.0
   --rpccorsdomain  "*" console

And it's the same for node B (update parameters specific to the node):

geth --datadir  nodeB   --networkid 1234 --rpc   --rpcport  9545  --port 9999 -
-rpcapi “db,eth,net,web3,personal,miner,admin”--cache=128 --rpcaddr --rpccorsdomain "*" console

Running Geth with the --rpc argument makes it operate as an HTTP JSON-RPC server. We have chosen different ports because, in this example, both nodes are running on the same physical machine. The following lists the meaning of some specified arguments, and you can refer to the official documentation for the others:

  • id: Network identifier. You can pick any value you want but avoid an ID of 0 to 3 as they are reserved.
  • rpcaddr: Specifies the HTTP-RPC server listening address (default: “localhost”).
  • rpcport: Specifies the HTTP-RPC server listening port (default: 8545). rpcapi: Specifies the APIs offered over the HTTP-RPC interface (default: eth, net, web3).
  • rpccorsdomain: Domains from which Geth accepts cross origin requests (browser enforced).

 

To connect both nodes, you can use any distinct, unused ports but you should set the same network ID. Be aware that the JSON RPC server is not recommended to be used over public internet, but only as a local interface:

Ethereum dapp with solidity and truffle


Connecting Ethereum nodes

As we have enabled the console mode in each node, we can execute commands provided by Geth. Therefore, to connect both nodes, we need to first get the node URL
using admin.nodeInfo.enode.
As a result, you'll get a value uniquely identifying your node, which can be used by another node to connect both nodes:

    admin.addPeer({"enode://7649de56ad54a0e6c712bb31db….32a789b9e@[::]:9999"})

Replace [::] with the node's IP address if you are using nodes in a network.
If everything went well, the net.peerCount command should return 1 in both consoles and admin.peers should return the list of currently connected peers.
It's worth noting that, for security reasons, Geth unlocks the accounts to prevent anyone other than the owner from performing any action or moving its funds. Therefore, you have to unlock an account before you start sending a transaction using the following:

web3.personal.unlockAccount("account address", "password", 0);

As account address, you can provide an address from those you got earlier, or just use eth.coinbase, which refers to the first account (in Ethereum, a single wallet can have many accounts, each having its own address). The second parameter is the password you provided when you created your account, and the last argument is the duration of unlocking. Having zero as a value means that the account will be unlocked until Geth stops running.

 

RPC tests

You can communicate with your nodes over RPC (outside of the Geth Terminal) to execute methods defined in web3 API. For instance, we can use CURL or some other command-line HTTP-fetching utility to request Geth's version over RPC as follows:

curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}'  -H 'content-type: text/plain;' http://127.0.0.1:8545/
{"jsonrpc":"2.0","id":67,"result":"Geth/v1.7.2-stable-1db4ecdc/linux- amd64/go1.9"}}

Mining process

As in other blockchains, to validate a transaction, whether it is intended to deploy or to interact with the contract, we need to have it mined and included in a block. To start mining with Geth, you'll need to run the following command in the geth console:
miner.start(x)

Here, x is an optional parameter representing the number of miner threads. This command will start the mining process, which will keep running even if there are no transactions to validate, creating empty blocks until you stop it manually using miner.stop(). The good news is that the mining process will generate new ether for you (valueless, of course).

A more convenient way would be to automatize the process of starting and stopping the mining process only when it's needed (when there are pending transactions). For this purpose, we need to first create a JavaScript file named mining.js, in which we define the following script:

var mining_threads = 1; function check() {
if (eth.getBlock("pending").transactions.length > 0) { if (eth.mining) {
return;
}
console.log("Mining in progress..."); miner.start(mining_threads);
} else {
miner.stop(0); console.log("Mining stopped.");
}
}

eth.filter("latest", function(err, block) { check();
});

eth.filter("pending", function(err, block) { check();
});
check();

Then load this script in the geth Terminal using
loadScript("/file_path/mining.js").

Contract deployment

Now your local Ethereum network is ready to process your transactions and to host your smart contract. Don't forget to make sure you unlocked your account and to mine a few blocks to get some ether.

In the Remix environment, you have to specify one of your node's IP address and RPC port will as the web3 provider. Thereafter, deploy your contract and edit your auction.js file with your new contract's address.

Congratulations! You have finished deploying the contract and you can start auctioning from the web page. In our next recipe, we will show you how to use Solidity compiler to deploy Ethereum contracts.

Recap

 

If you love compiling and running code using command lines, you can use the Solidity compiler, solc. To use the latest stable version of the Solidity compiler, run the following:

  sudo  apt-get update
sudo apt-get install solc

Start by copying the contract code into a file named auction.sol, and afterwards run the following command to compile the contract and generate the needed ABI and bytecode.
The output will be saved in a details.js file as follows:

  echo "var  ContractDetails=`solc --optimize --combined-json abi,bin auction.sol`"  > details.js

If you see a set of warnings, neglect them and then run in succession the following commands in your Geth CLI, in succession:

  loadScript(“your Path/details.js”)
var ContractAbi = ContractDetails.contracts["auction.sol:MyAuction"].abi; var ContractInstance = eth.contract(JSON.parse(ContractAbi));
var ContractBin = "0x" + ContractDetails.contracts["auction.sol:MyAuction"].bin;

Before you continue, make sue you have unlocked your first account:

var deploymentTransationObject = { from: eth.accounts[0], data: ContractBin, gas: 1000000 };

  var auctionInstance = ContractInstance.new(deploymentTransationObject);  var AuctionAddress =
eth.getTransactionReceipt(auctionInstance.transactionHash).contractAddress;

From the console, to interact with the contract, you can create an object pointing to your contract's address as follows:

var Mycontract =  ContractInstance.at(AuctionAddress);

This is similar to what we have done so far in Web3Js and, depending on the nature of the function, we can execute a call using Mycontract.FunctionName.call() or send a transaction using Mycontract.FunctionName.sendTransaction(FunctionArguments, {from: eth.accounts[0], gas: 1000000}).
In order to validate your transaction, you'll need to run the mining process in Geth using miner.start() or use the mining script we used earlier when we configured the private chain.

Here, we have seen a winding path for compiling and deploying a contract using solc, web3.js, and a local blockchain. Tools such as Truffle (that you'll discover in our follow-up recipes) do all that for you under the hood, and make perfect alternatives for quick development and testing.

 

Proof of authority (POA) and difficulty adjustment

In the previous procedure of running a local network, we used the Geth client with POW mining to validate the transaction. However, you may find mining a daunting process as its difficulty will rise, causing annoying, heavy computations reducing your system capacity even if we set it as low as possible in the genesis file.

To solve this issue, you have two choices: either configure the network to use an alternative mining mechanism called POA, or fix the mining difficulty in the Geth client source code. Let's have a look at these possibilities.

 

Option 1 – editing the Ethereum client code

To explore this option, you'll need to do some Golang hacking! Don't worry; there's nothing complex.

In Geth's code (the consensus.go file at; https://github.com/ethereum/go-ethereum/blob/master/consensus/ethash/consensus.go), there is a function called CalcDifficulty that represents the difficulty adjustment algorithm. It returns the difficulty that a new block should have when created, given the parent block's time and difficulty. To fix the difficulty, we need to fix the returned value as follows:

func CalcDifficulty(config *params.ChainConfig, time uint64, parent

  *types.Header) *big.Int { return  big.NewInt(1)
}

Afterwards, compile your new Geth client following the instructions presented in the official Geth GitHub repository at https://github.com/ethereum/go-ethereum/wiki/ Installing-Geth .

 

Option 2 – POW

An alternative solution to avoid relying on proof of work (POW) mining is to use a replacement consensus mechanism known as POA, in which we trust a set of known validators (authorities) to accept transactions. In other words, POA validators are staking their identity and voluntarily disclosing who they are in exchange for the right to validate the blocks. Unlike POW, POA is a centralized mechanism that delivers comparatively fast transactions, thus POA deployment is used by private (enterprise) and some public testing networks (for example, the popular Kovan and Rinkeby test networks).

 

To set up a private chain with Geth and POA, you will need to reiterate the same Puppeth procedure that was presented earlier, except for choosing the consensus engine. Start Puppeth, follow the questionnaire, and choose POA as the consensus engine. In this case, you'll need to determine the validator accounts (accounts that are allowed to seal). For that, copy and paste the Ethereum accounts that were created earlier by Geth. Of course, you can define as many sealers as you like but POA is able to work with a single node and only one sealer:

Ethereum dapp development

Keep in mind that POA doesn't have mining rewards, and therefore it's highly recommended that you allocate enough ether (defined in the unit of wei) to your accounts first, and then initialize your nodes with the resultant POA genesis file.

After laying out the different available deployment environments, it's time to run our auction DApp in our next recipe.

Recap

 

At this level, you should have already deployed your contract on one of the deployment environments presented beforehand. To try what we have built so far, follow these instructions:

Ethereum dapp development


To start interacting with this DApp, the easiest method is to use MetaMask connected to Ganache. In this case, we'll need to import some of the accounts created by Ganache into MetaMask. To do that, we copy the private key from the Ganache interface and in MetaMask, we import the corresponding accounts by following the instructions presented in the official documentation (https://metamask.zendesk.com/hc/en-us/articles/ 360015489351-Importing-Accounts) or if you're using the new UI (https://metamask.zendesk.com/hc/en-us/articles/360015489331-Importing-an-Account-New-UI-). Once the accounts have been imported, write your bid amount in the bid input and press the  Bid! button. MetaMask will prompt you to accept this transaction and let you know the fee you have to pay. To make it competitive, change the bidder account in MetaMask and make a new bid. Each time a new bid is accepted, the auction details board on the right will be updated.

 

Contract and transaction cost

One of good signs of good Solidity code is the cheap cost of its operations, thus in your contract you should optimize your code cost as much as possible.

As we stated in the introduction, Ethereum is a "paying" network and you're invoiced in gas. We learned earlier that gas has multiple metrics associated with it:

  • Gas cost: A static value for how much a computation costs in terms of gas. Gas price: Expresses how much the gas costs in ether. The price of gas itself is meant to stay generally constant.
  • Gas limit: There are two limits, the block gas limit and transaction gas limit. Each transaction has a gas limit set by the sender, whereas the block gas limit (defined by the network) determines how many transactions can fit in a block.
  • Gas fee: Effectively, the amount of gas needed to be paid to run a particular transaction or program (called a contract).

 

The idea behind the gas system is to have a dedicated unit to quantify transaction or computation cost on the Ethereum network. This fueling system is used to incentivize miners and to avoid denial of service attacks through malicious scripts that run forever. If the smart contract cannot complete before running out of ether, it is halted at that point.
In general, gas is consumed by a contract in two situations: Contract deployment
Contract execution through transactions


How cost is calculated

Higher-level languages such as Solidity compile down to EVM bytecode, translating the contract code into a list of smallest units of computation, called opcodes. These include operations such as ADD (addition operation), SLOAD (load word from storage), and CREATE (create a new account with associated code). The gas cost for each opcode can be found in the yellow paper, and is also listed at https://github.com/bellaj/evm-opcode- gas-costs. The total cost for a given instruction is the sum of the executed corresponding opcodes.

The Ethereum yellow paper defines approximately 130 opcodes. Each of these opcodes has an associated fixed gas price, with some opcodes costing more gas than others. For example, ADD uses three gas units while MUL (multiply two integers) uses five gas,
hence MUL is more complex than ADD. Knowing these costs mean that you can optimize your code by avoiding expensive operations (opcodes).

 

Deployment cost

To deploy the contract, you have to pay for adding bytecode (the runtime bytecode  stripped of initialization data) to the blockchain at a cost of 200 gas/byte, plus a fee of 32,000 gas for creating the contract account (create opcode), as indicated in the Ethereum yellow paper. In our case, the contract deployment costs approximately 1,054,247 gas units, and with a gas price of 2 gwei (1 ether = 1000000000 gwei), it will cost a total of 0.002108494 ether.

To reduce your cost, at this level, you'll need to optimize the code size and get rid of useless code and state variables.

 

Function execution cost

You can use Remix connected to the testnet to get an estimation cost of each function call. The following table presents the cost of the main methods defined in the auction contract according to Remix:
Ethereum dapp development


A basic transaction (simple transfer of ETH) has a minimum gas requirement of 21,000 gas. Consequently, if you are just transferring funds and not interacting with a contract, your transaction takes 21,000 gas. If you are interacting with a contract, your transaction takes 21,000 gas, plus any gas associated with the executed method.

 

Contract destruction cost

The selfdestruct() function has an interesting feature as it enables us to reduce the cost of the destruction transaction. It's based on the SUICIDE opcode, which uses negative gas because the operation frees up space on the blockchain by clearing all of the contract's state data. This negative gas is deducted from the total gas cost of the transaction, therefore reducing your gas cost. In our case, this method costs 14,211 gas, less than a normal transfer (which costs 21,000 gas):
Ethereum dapp development

 

Potential optimization

The opcode gas prices give us an idea about which operations to use with moderation. For instance, reading from storage costs 200 gas per SLOAD instruction, and writing to storage SSTORE costs 5,000 gas, but reading from the EVM's memory and writing to it costs only 3 gas. Therefore, it's preferable to avoid extensive reading/writing operations from and into storage but instead use the memory.


The cost also depends on data size, with the fee being 20,000 gas to store a 256-bit word. For example, a kilobyte (8,000 bits) costs 640k gas, and with a gas price of 18 Gwei, you'll have to pay 11,520,000 Gwei (0.01152 Ether), or about 6.8659 USD (at 595.997$ per ether), making Ethereum an expensive storage infrastructure. Another bottleneck of storing data is the current block gas limit of approximately 8,000,000 gas/block (https://ethstats.net). At this cap of gas per block, it would take over 80 blocks to write 1 MB of data to the blockchain, and that is assuming you can manage to reserve all of the gas per block and  that there are no other operations required!

The following is some optimization advice related to data storage:

  • Use bytes1 to bytes32 instead of string for small strings or bytes data that's longer than 32 bytes. They are much cheaper.
  • Preferably, use fixed length arrays instead of dynamically sized arrays. The indexed parameters in events have additional gas cost.
  • For struct elements, you should use shorter types, as well as sorting them so that short types would be grouped together into single storage slot. By doing this, you can decrease the gas costs by combining multiple SSTORE operations into one.
  • According to the yellow paper, it costs 375 gas for each topic in a LOG operation and 8 gas for each byte of a LOG operation's data. Consequently, logs are considered as a cheaper storage solution; however, unlike storage, logs aren't readable by a smart contract.
  • By making the state of your contracts public, you have your compiler create getters automatically, which reduces contract size and therefore cost.

 

For a better design in our example, we can use an off-chain environment to store the car or user details, and only keep in the contract a referencing URL. In general, it's wise to find the balance between using on-chain and off-chain environments, while still leveraging the decentralized capabilities of the blockchain.


Solidity tips and tricks

We end this recipe with some recommendations and best practices you can adopt while you write your smart contracts:

  • There is no size limit to the data sent along your transaction. You will be only limited by how much ether you have and the block gas limit.
  • Constants are not stored in contract storage. A constant state such as uint256 constant x = block.timestamp; means that contract will re-evaluate x every time it is used.
  • Remember that calls to external functions can fail, therefore always check the return value.
  • For transferring funds, it's preferable to use transfer() over send() as transfer() is equivalent to require(send()) and will throw if it doesn't execute successfully.
  • Be aware that the block's timestamp can be influenced a little bit by miners. It's safe to use block.timestamp if your contract function can tolerate a 30-second drift in time, since the tolerated NTP drift is 10 seconds, as defined in https://github.com/ethereum/go-ethereum/blob/master/p2p/discover/udp.go#L57. Don't be confused if you read in the yellow paper (the old version) that a tolerable drift interval of up to 900 seconds (15 minutes) is allowed. This is outdated information.
  • There's a limit in Solidity to how many variables you can define in a function (including parameters and return variables). The limit is 16 variables, otherwise you get the StackTooDeepException error.
  • Contracts can't trigger themselves but they need an external poke (for example, a contract can't automatically do something at specific time, like a Cron job, unless it receives an external signal).

 

Hopefully, throughout first set of recipes, you were able to develop an understanding of the fundamentals of DApps and smart contract development. We covered, in a simplified way, the basics of Solidity and web3.js and how to build and deploy a simple full DApp.
While we have created a working DApp, it's by no means the final word in smart contract security and structural optimization. You'll still need to define functions to transfer ownership and open a bid, and add over- and underflow protection measures, just to name a few.
In the next round of recipes, we will take the learning process a step further, covering new concepts in Ethereum and digging deeper into Solidity's advanced features, such as optimization, debugging, and security.

Resources

Free Webinars on Blockchain

Here is the list of our free webinars that are highly recommended:

Free Courses

Here is the list of our 10 free self-paced courses that are highly recommended:

Self-Paced Blockchain Courses

If you like to learn more about Hyperledger Fabric, Hyperledger Sawtooth, Ethereum or Corda, taking the following self-paced classes is highly recommended:

  1. Intro to Blockchain Technology
  2. Blockchain Management in Hyperledger for System Admins
  3. Hyperledger Fabric for Developers
  4. Intro to Blockchain Cybersecurity
  5. Learn Solidity Programming by Examples
  6. Introduction to Ethereum Blockchain Development
  7. Learn Blockchain Dev with Corda R3
  8. Intro to Hyperledger Sawtooth for System Admins

Live Blockchain Courses

If you want to master Hyperledger Fabric, Ethereum or Corda, taking the following live classes is highly recommended:

 

Articles and Tutorials on Blockchain Technology

If you like to learn more about blockchain technology and how it works, reading the following articles is highly recommended:

Articles and Tutorials on Ethereum and Solidity

If you like to learn more about blockchain development in Ethereum with Solidity, reading the following articles and tutorials is highly recommended:

Articles and Tutorials on Hyperledger Family

If you like to learn more about blockchain development with Hyperledger, reading the following articles and tutorials is highly recommended:

Articles and Tutorials on R3 Corda

If you like to learn more about blockchain development on Corda , reading the following articles and tutorials is highly recommended:

Articles and Tutorials on Other Blockchain Platforms

If you like to learn more about blockchain development in other platforms, reading the following articles and tutorials is highly recommended:


View Our Classes!