Reader small image

You're reading from  Building Blockchain Projects

Product typeBook
Published inApr 2017
Reading LevelBeginner
PublisherPackt
ISBN-139781787122147
Edition1st Edition
Languages
Right arrow
Author (1)
Narayan Prusty
Narayan Prusty
author image
Narayan Prusty

Narayan Prusty is a full-stack developer. He works as a consultant for various start-ups around the world. He has worked on various technologies and programming languages but is very passionate about JavaScript, WordPress, Ethereum, Solr, React, Cordova, MongoDB, and AWS. Apart from consulting for various start-ups, he also runs a blog titled QNimate and a video tutorial site titled QScutter, where he shares information about a lot of the technologies he works on.
Read more about Narayan Prusty

Right arrow

Chapter 3. Writing Smart Contracts

In the previous chapter, we learned how the Ethereum blockchain works and how the PoW consensus protocol keeps it safe. Now it's time to start writing smart contracts as we have have a good grasp of how Ethereum works. There are various languages to write Ethereum smart contracts in, but Solidity is the most popular one. In this chapter, we will learn the Solidity programming language. We will finally build a DApp for proof of existence, integrity, and ownership at given a time, that is, a DApp that can prove that a file was with a particular owner at a specific time.

In this chapter, we'll cover the following topics:

  • The layout of Solidity source files
  • Understanding Solidity data types
  • Special variables and functions of contracts
  • Control structures
  • Structure and features of contracts
  • Compiling and deploying contracts

Solidity source files


A Solidity source file is indicated using the .sol extension. Just like any other programming language, there are various versions of Solidity. The latest version at the time of writing this book is 0.4.2.

In the source file, you can mention the compiler version for which the code is written for using the pragma Solidity directive.

For example, take a look at the following:

pragma Solidity ^0.4.2; 

Now the source file will not compile with a compiler earlier than version 0.4.2, and it will also not work on a compiler starting from version 0.5.0 (this second condition is added using ^). Compiler versions between 0.4.2 to 0.5.0 are most likely to include bug fixes instead of breaking anything.

Note

It is possible to specify much more complex rules for the compiler version; the expression follows those used by npm.

The structure of a smart contract


A contract is like a class. A contract contains state variables, functions, function modifiers, events, structures, and enums. Contracts also support inheritance. Inheritance is implemented by copying code at the time of compiling. Smart contracts also support polymorphism.

Let's look at an example of a smart contract to get an idea about what it looks like:

contract Sample 
{ 
    //state variables 
    uint256 data; 
    address owner; 

    //event definition 
    event logData(uint256 dataToLog);  

    //function modifier 
    modifier onlyOwner() { 
        if (msg.sender != owner) throw; 
        _; 
    } 

    //constructor 
    function Sample(uint256 initData, address initOwner){ 
        data = initData; 
        owner = initOwner; 
    } 

    //functions 
    function getData() returns (uint256 returnedData){ 
        return data; 
    } 

    function setData(uint256 newData) onlyOwner{ 
        logData(newData); 
        data = newData; 
 ...

Data location


All programming languages you would have learned so far store their variables in memory. But in Solidity, variables are stored in the memory and the filesystem depending on the context.

Depending on the context, there is always a default location. But for complex data types, such as strings, arrays, and structs, it can be overridden by appending either storage or memory to the type. The default for function parameters (including return parameters) is memory, the default for local variables is storage. and the location is forced to storage, for state variables (obviously).

Data locations are important because they change how assignments behave:

  • Assignments between storage variables and memory variables always create an independent copy. But assignments from one memory-stored complex type to another memory-stored complex type do not create a copy.
  • Assignment to a state variable (even from other state variables) always creates an independent copy.
  • You cannot assign complex types stored...

What are the different data types?


Solidity is a statically typed language; the type of data a variable holds needs to be predefined. By default, all bits of the variables are assigned to 0. In Solidity, variables are function scoped; that is, a variable declared anywhere within a function will be in scope for the entire function regardless of where it is declared.

Now let's look at the various data types provided by Solidity:

  • The most simple data type is bool. It can hold either true or false.
  • uint8, uint16, uint24 ... uint256 are used to hold unsigned integers of 8 bits, 16 bits, 24 bits ... 256 bits, respectively. Similarly, int8, int16 ... int256 are used to hold signed integers of 8 bits, 16 bits ... 256 bits, respectively. uint and int are aliases for uint256 and int256. Similar to uint and int, ufixed and fixed represent fractional numbers. ufixed0x8, ufixed0x16 ... ufixed0x256 are used to hold unsigned fractional numbers of 8 bits, 16 bits ... 256 bits, respectively. Similarly, fixed0x8...

Control structures


Solidity supports if, else, while, for, break, continue, return, ? : control structures.

Here is an example to demonstrate the control structures:

contract sample{ 
    int a = 12; 
    int[] b; 

    function sample() 
    { 
        //"==" throws exception for complex types  
        if(a == 12) 
        { 
        } 
        else if(a == 34) 
        { 
        } 
        else 
        { 
        } 

        var temp = 10; 

        while(temp < 20) 
        { 
            if(temp == 17) 
            { 
                break; 
            } 
            else 
            { 
                continue; 
            } 

            temp++; 
        } 

        for(var iii = 0; iii < b.length; iii++) 
        { 

        } 
    } 
} 

Creating contracts using the new operator


A contract can create a new contract using the new keyword. The complete code of the contract being created has to be known.

Here is an example to demonstrate this:

contract sample1 
{ 
    int a; 

    function assign(int b) 
    { 
        a = b; 
    } 
} 


contract sample2{ 
    function sample2() 
    { 
        sample1 s = new sample1(); 
        s.assign(12); 
    } 
} 

Exceptions


There are some cases where exceptions are thrown automatically. You can use throw to throw an exception manually. The effect of an exception is that the currently executing call is stopped and reverted (that is, all changes to the state and balances are undone). Catching exceptions is not possible:

contract sample 
{ 
    function myFunction() 
    { 
        throw; 
    } 
} 

External function calls


There are two kinds of function calls in Solidity: internal and external function calls. An internal function call is when a function calls another function in the same contract.

An external function call is when a function calls a function of another contract. Let's look at an example:

contract sample1 
{ 
    int a; 

    //"payable" is a built-in modifier 
    //This modifier is required if another contract is sending Ether while calling the method 
    function sample1(int b) payable 
    { 
        a = b; 
    } 

    function assign(int c)  
    { 
        a = c; 
    } 

    function makePayment(int d) payable 
    { 
        a = d; 
    } 
} 


contract sample2{ 

    function hello() 
    { 
    } 

    function sample2(address addressOfContract) 
    { 
        //send 12 wei while creating contract instance 
        sample1 s = (new sample1).value(12)(23); 

        s.makePayment(22); 

        //sending Ether also 
        s.makePayment.value(45)(12); 

...

Features of contracts


Now it's time to get deeper into contracts. We will look at some new features and also get deeper into the features we have already seen.

Visibility

The visibility of a state variable or a function defines who can see it. There are four kinds of visibilities for function and state variables: external, public, internal, and private.

By default, the visibility of functions is public and the visibility of state variables is internal. Let's look at what each of these visibility functions mean:

  • external: External functions can be called only from other contracts or via transactions. An external function f cannot be called internally; that is, f() will not work, but this.f() works. You cannot apply the external visibility to state variables.
  • public: Public functions and state variables can be accessed in all ways possible. The compiler generated accessor functions are all public state variables. You cannot create your own accessors. Actually, it generates only getters, not setters...

Libraries


Libraries are similar to contracts, but their purpose is that they are deployed only once at a specific address and their code is reused by various contracts. This means that if library functions are called, their code is executed in the context of the calling contract; that is, this points to the calling contract, and especially, the storage from the calling contract can be accessed. As a library is an isolated piece of source code, it can only access state variables of the calling contract if they are explicitly supplied (it would have no way to name them otherwise).

Libraries cannot have state variables; they don't support inheritance and they cannot receive Ether. Libraries can contain structs and enums.

Once a Solidity library is deployed to the blockchain, it can be used by anyone, assuming you know its address and have the source code (with only prototypes or complete implementation). The source code is required by the Solidity compiler so that it can make sure that the methods...

Returning multiple values


Solidity allows functions to return multiple values. Here is an example to demonstrate this:

contract sample 
{ 
    function a() returns (int a, string c) 
    { 
        return (1, "ss"); 
    } 

    function b() 
    { 
        int A; 
        string memory B; 

        //A is 1 and B is "ss" 
        (A, B) = a(); 

        //A is 1 
        (A,) = a(); 

        //B is "ss" 
        (, B) = a(); 
    } 
} 

Importing other Solidity source files


Solidity allows a source file to import other source files. Here is an example to demonstrate this:

//This statement imports all global symbols from "filename" (and symbols imported there) into the current global scope. "filename" can be a absolute or relative path. It can only be a HTTP URL 
import "filename"; 

//creates a new global symbol symbolName whose members are all the global symbols from "filename". 
import * as symbolName from "filename"; 

//creates new global symbols alias and symbol2 which reference symbol1 and symbol2 from "filename", respectively. 
import {symbol1 as alias, symbol2} from "filename"; 

//this is equivalent to import * as symbolName from "filename";. 
import "filename" as symbolName; 

Globally available variables


There are special variables and functions that always exist globally. They are discussed in the upcoming sections.

Block and transaction properties

The block and transaction properties are as follows:

  • block.blockhash(uint blockNumber) returns (bytes32): The hash of the given block only works for the 256 most recent blocks.
  • block.coinbase (address): The current block miner's address.
  • block.difficulty (uint): The current block difficulty.
  • block.gaslimit (uint): The current block gas limit. It defines the maximum amount of gas that all transactions in the whole block combined are allowed to consume. Its purpose is to keep the block propagation and processing time low, thereby allowing a sufficiently decentralized network. Miners have the right to set the gas limit for the current block to be within ~0.0975% (1/1,024) of the gas limit of the last block, so the resulting gas limit should be the median of miners' preferences.
  • block.number (uint): The current block number...

Ether units


A literal number can take a suffix of wei, finney, szabo, or Ether to convert between the subdenominations of Ether, where Ether currency numbers without a postfix are assumed to be wei; for example, 2 Ether == 2000 finney evaluates to true.

Proof of existence, integrity, and ownership contract


Let's write a Solidity contract that can prove file ownership without revealing the actual file. It can prove that the file existed at a particular time and finally check for document integrity.

We will achieve proof of ownership by storing the hash of the file and the owner's name as pairs. We will achieve proof of existence by storing the hash of the file and the block timestamp as pairs. Finally, storing the hash itself proves the file integrity; that is, if the file was modified, then its hash will change and the contract won't be able to find any such file, therefore proving that the file was modified.

Here is the code for the smart contract to achieve all this:

contract Proof 
{ 
    struct FileDetails 
    { 
        uint timestamp; 
        string owner; 
    } 

    mapping (string => FileDetails) files; 

    event logFileAddedStatus(bool status, uint timestamp, string owner, string fileHash); 

    //this is used to store the...

Compiling and deploying contracts


Ethereum provides the solc compiler, which provides a command-line interface to compile .sol files. Visit http://solidity.readthedocs.io/en/develop/installing-solidity.html#binary-packages  to find instructions to install it and visit https://Solidity.readthedocs.io/en/develop/using-the-compiler.html  to find instructions on how to use it. We won't be using the solc compiler directly; instead, we will be using solcjs and Solidity browser. Solcjs allows us to compile Solidity programmatically in Node.js, whereas browser Solidity is an IDE, which is suitable for small contracts.

For now, let's just compile the preceding contract using a browser Solidity provided by Ethereum. Learn more about it at https://Ethereum.github.io/browser-Solidity/. You can also download this browser Solidity source code and use it offline. Visit https://github.com/Ethereum/browser-Solidity/tree/gh-pages  to download it.

A major advantage of using this browser Solidity is that it provides...

Summary


In this chapter, we learned the Solidity programming language. We learned about data location, data types, and advanced features of contracts. We also learned the quickest and easiest way to compile and deploy a smart contract. Now you should be comfortable with writing smart contracts.

In the next chapter, we will build a frontend for the smart contract, which will make it easy to deploy the smart contract and run transactions.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Building Blockchain Projects
Published in: Apr 2017Publisher: PacktISBN-13: 9781787122147
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Narayan Prusty

Narayan Prusty is a full-stack developer. He works as a consultant for various start-ups around the world. He has worked on various technologies and programming languages but is very passionate about JavaScript, WordPress, Ethereum, Solr, React, Cordova, MongoDB, and AWS. Apart from consulting for various start-ups, he also runs a blog titled QNimate and a video tutorial site titled QScutter, where he shares information about a lot of the technologies he works on.
Read more about Narayan Prusty