Ethereum Solidity Compiler


Ethereum contracts are written in the high level language called Solidity and compiled into bytecode using the Solidity compiler. This bytecode is then uploaded on to the blockchain.

As mentioned in the previous blog, Visual Studio Code and several editors provide integrated environment to compile the code. If you want to manually run the compiler then here are the steps for compiling a smart contract.

Download the compiler from the GitHub release site
Based on your platform download the corresponding bits

Open the command line and run the below command to compile our 0xService or any smart contract
%path%\solc.exe --bin --abi --overwrite -o bin Service.sol

As you see in the above we are passing bin and abi arguments to specify to the compiler to create the bin and abi file. The generated files are created in the bin folder as mentioned by the other bin attribute. The overwrite flag is used to overwrite the previously generated abi and bytecodes.

0x Services Objective & Requirements


Below are the objective and requirements of 0x platform

Objective:
Provide a decentralized platform where a client can post a service request and a provider or contractor perform the service in a trustless environment and with escrow payment system.

Requirements:
Client
  • Register and create an account with 0x. 0x creates an user account in Ethereum chain
  • Post a service request in 0x and set its price in Ether or 0x tokens. 0x creates a smart contract on Ethereum chain
  • 0x charges a small amount of fee for creating the contract, this is in addition to the gas required by Ethereum chain. This fee will be paid through 0x tokens
  • Negotiate the price of the service with the provider (out of scope for POC)
  • The contract acts as the escrow account. Fund the contract with the agreed service amount. This funding can be done through Ether or 0x tokens.
  • Once the work is complete authorize payment to the contractor.
  • Settle disputes with help of arbiter

Contractor
  • Register and create an account with 0x. 0x creates an user account in Ethereum chain
  • Apply for a service
  • Perform the requested service (outside of 0x)
  • Request payment for the service
  • Receive payment to the account
  • Raise arbitration if the payment is not received

Arbiter
  • Settle the dispute and authorize the payment from escrow account.
  • 0x acts as the default arbiter. The client can choose his own arbiter.


The below are the out of scope requirements for the current implementation and these can be taken up at a later time.
  • Terms and Conditions of the work which will be checked before the payment is made
  • Termination procedure
  • Intermediate payment or payment schedule where the contractor gets payments based on the payment terms

s

Visibility Modifiers


Solidity exposes state variables and functions to internal and external worlds using the visibility modifiers. There are four types of visibility modifiers public, internal, private and external.

Functions can have all the four visibility modifiers, the default visibility modifier for functions is public. State variables cannot have external visibility modifier and the default modifier is internal.

Below is the brief description and usage of these visibility modifiers for state variables and functions:

public

Public functions are part of the contract interface and can be either accessible within the contract or via messages. Public state variables are accessible similar to the functions.
contract Service {
    address public arbiter; // 0x is the default arbiter for every contract
    address contractor;

    /// @notice Once the service is completed, client pays to the contractor
    function pay() public {
        contractor.transfer(amountPaid);
        amountPaid = 0;
    }
}

For public State variables Solidity automatically generates a getter function. In the above contract, arbiter is defined as public, Solidity generates a function called arbiter which returns the arbiter address.

internal

The internal functions and state variables can only be accessed within the contract or derived contracts. This is similar to protected variables in C# and other object oriented programming.
In the above code, contractor state variable does not have any visibility modifier. As per default configuration, the contract state variable will be on internal scope.

private

Private functions and state variables, like the name indicates, are accessible within the contract they defined. They are not available in the derived contracts.

external

An external function is similar to public function. In addition from being called internally and via transactions, external functions can be called from other contracts. To call an external function internally it needs to be prefixed with this (this.fund()). External functions can access other functions and state variable directly (without the prefix of this)
/// @notice based on the agreement, client will fund the contract
/// this amount will be payed to contractor at the end
function fund() external onlyClient payable {
    amountPaid += msg.value;
}


As mentioned earlier State variables cannot have external visibility modifier. Only functions can have external visibility modifier.

Solidity Constant


Solidity supports to declare constant state variables and functions. A keyword constant is used to define constants in Solidity.

Constant State Variables

State variables can be declared as constant. All constant state variables should be assigned to a constant value at compile time. It can have an expression, but that expression should be evaluated to constant at compile time. Solidity only supports value types and string types as constants. Here is an example of defining constant static variable from Ethereum documentation. Currently in our contract we do not need this constant variables.

contract C {
    uint constant x = 32**22 + 8;
    string constant text = "abc";
    bytes32 constant myHash = keccak256("abc");
}

Constant Functions

Constant function are those functions which does not modify the state of the contract. These functions are used to return values from the contract. In our 0x service contract we defined a constant function which returns the address of the contractor.
/// @notice Get the contractor assigned to the service
/// @return contractor address
function getContractorAddress() public constant returns (address) {
    return contractor;
}

Ethereum Solidity Function Parameters


Solidity functions, like any other programming language, take input parameters and return output parameters. They can also return arbitrary number of parameters as output (this is similar to Tuples in C# 7). 

Input Parameters

The input parameters are defined same as variables. A function can take multiple number of input parameters. In our service if we want to hire a contractor we specify the contract address as the input parameter.
/// @notice hiring the contractor to perform the work
/// @param _contractor ethereum address of the contractor
function hire (address _contractor) onlyClient {
    contractor = _contractor;
}

Output Parameters

Solidity functions support multiple ways of returning parameters. The function return type should be declared with returns keyword. In our service if we want to return the contractor address, then we would write as below:
/// @notice Get the contractor assigned to the service
/// @return contractor address
function getContractorAddress() public constant returns (address) {
    return contractor;
}

Similar to other languages we can use the keyword return to return the function output. Solidity supports named parameters we can provide name of the return parameter as shown below:
/// @notice Get the contractor assigned to the service
/// @return contractor address
function getContractorAddress() public constant returns (address _contractor) {
    _contractor = contractor;
}

In the above code we provided variable name to the return parameter, _contractor. Assigning value to the variable will automatically return its value.

Solidity supports returning values. It internally uses tuple types, i.e. a list of objects of potentially different types whose size is a constant at compile-time. Those tuples can be used to return multiple values at the same time. The functionality is similar to tuples in C# 7. Let’s return all the addresses in our Service Contract
/// @notice Get the addresses of client, contractor and 0x platform
/// @return client, contractor and platform address
function getAllAddresses() public constant returns (address, address, address) {
    return (client, contractor, platform);
}


Ethereum Solidity Comments


Similar to JavaScript, Solidity supports single line comments (//) and multi-line comments (/*…*/) as shown below

// This is a single-line comment.

/*
This is a
multi-line comment.
*/

Solidity contracts can also have a special form of comments for documentation. This documentation type of comments is called Ethereum Natural Specification Format (Natspec). Natspec format uses doxygen tags. It can have either one or multiple lines starting with /// or a multiline comment starting with /** and ending with */. Here is how we are using Natspec documentation in our service contract.

/// @title contract between client and contractor.
contract Service {
    address contractor; // address of the hired contractor

    /// @notice Hiring the contractor to perform the work
    /// @param _contractor Ethereum address of the contractor
    function hire (address _contractor) onlyClient {
        contractor = _contractor;
    }

    /// @notice Get the contractor assigned to the service
    /// @return contractor address
    function getContractorAddress() public constant returns (address) {
        return contractor;
    }
}

In the above code we documented the title of the contract. We also documented the two functions along with their parameters. This documentation comments are parsed by Natspec client and create documentation json files.

Ethereum Solidity


Solidity is a contract-oriented, high-level programming language for writing smart contracts which run on Ethereum Virtual Machine. Solidity language is statically typed and follows object-oriented principles.  It supports inheritance, libraries and complex user-defined types. Solidity’s syntax is similar to that of ECMA Script (JavaScript) syntax making it familiar for existing web developers.

Here is the Hello World solidity code we looked earlier.
pragma solidity ^0.4.14;

contract HelloWorld {

    function greet() public constant returns (string) {
        return "Hello World!";
    }
}

Solidity code is compiled to bytecode that is executable on the EVM. We can use solc, the solidity compiler, or developer editors such as Visual Studio Code to compile and generate the bytecode. Here is the bytecode for the above Hello World sample.

6060604052341561000c57fe5b5b6101498061001c6000396000f300606060405263ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663cfae3217811461003a575bfe5b341561004257fe5b61004a6100ca565b604080516020808252835181830152835191928392908301918501908083838215610090575b80518252602083111561009057601f199092019160209182019101610070565b505050905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100d261010b565b5060408051808201909152600c81527f48656c6c6f20576f726c6421000000000000000000000000000000000000000060208201525b90565b604080516020810190915260008152905600a165627a7a723058205168b085c257b42e405c11a8e900935fd85bd351767a3ed78211b54b7c6df2e10029

Solidity also uses an application binary interface (ABI). ABI defines the structure and methods used in the contract. Ethereum internally uses ABI for encoding and decoding data into and out of transactions. We can use this ABI during contract deploying and also to decode the data passed with transactions. Here is the ABI for our Hello World code.

[{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}]


Data Types in Ethereum Solidity Smart Contracts


Solidity is a statically typed language which employs a type system that allows compiler to check for correct usage of variables. Solidity compiler forces that every variable be defined at compile time. Solidity language provides several basic types. These basic types can be combined to form complex types.

Like other static type languages such as C#, Solidity has Value types and Reference types. Solidity Value Types and Reference Types behave similar to C# as outlined below:

Value Types: Value Type variables are always passed by value. These variables are copied when they are used as function arguments or in assignment. These are basic data types provided by Solidity

Reference Types: These are the complex data types that cannot be copied. Their memory or data location is passed around.

Below are the popular data types used in Solidity. For more information refer to the Solidity documentation http://solidity.readthedocs.io/en/latest/types.html
  • Value Types
    • Boolean
    • Integer
    • Address
    • Enum
    • Function
  • Reference Types
    • String
    • Array
    • Struct
    • Mapping
Here are the brief details of the common data types in Solidity

Boolean

Boolean data type is used to store true or false value. This is similar to C# and other programming languages.

Boolean supports all the typical comparison operators such as ! , ||, &&, ==, !=. The operators || and && apply the common short-circuiting rules. This means that in the expression f(x) || g(y), if f(x) evaluates to true, g(y) will not be evaluated.

Integer

Solidity support signed and unsigned integers. Signed integers are declared with keyword int and unsigned integers with keyword uint. In addition to better optimize memory Solidity allows specifing the size of the integer data types, such as uint8, uint16, …, uint256 and int8, int16, …, int256. The size of the data types varies by a step of 8 bits. Solidity provided a short hand alias of uint for uint256 and int for int256. This is similar to int alias in C#.

uint budget; // amount budgeted for the service
uint amountPaid; // amount paid to the contractor

Like other languages (C#), Solidity provides the following operators
  • Comparison operators: <=, <, ==, !=, >=, >
  • Bit operators: &, |, ^, ~
  • Arithmetic Operators: +, -, *, /, %
  • Unary operators: ++, --
  • Assignment operators: -=, *=, /=, %=, |=, &=, ^=

String

Strings are the dynamic sized array (see below for Arrays). This type is used to store an arbitrary length of string. As Strings are arrays they are reference type.

Solidity also supports string literals which are fixed sized byte arrays. String literals are written with either double or single quotes (“Client”, ‘Contractor’). Similar to integer data types, the string literals can have the data types of bytes1, ..., bytes32 (depending on the string size)

Address

Address data type is used to store an Ethereum address. It can contain the address of a user account or an address of a contract. Ethereum address is a 20 byte value as shown below:

// 0x account address
address platformAddress = 0x1e2f51e97f2772dafe59d345bbe48c32a7d2b46b;

The Address data type has below two frequently used members:
  • balance() returns(uint): This method returns the ether balance of the address in units of wei
  • transfer(uint): This method is used to send ethers from the current contract address to another address. The ethers are defined in the units of wei.

Enum

The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list. Hence Enums are strongly typed constants which makes the code more readable and less prone to errors.

// enum to define states of the service contract
enum State { Bid, Award, Work, Paid }
State contractState; // to store the current state of the service contract

Enums need at least one member. Enum types have to be explicitly converted from and to integer types. Solidity sometimes implicitly convert the enum types when used in function return parameters.

Function Types

Function Types are the types of functions. Similar to Java Script, Solidity allows functions to be passed as function parameters and return types. Solidity functions can be assigned to a variable of Function Type. These variables can be passed as inputs to the functions and can be returned as function return values. Function Types comes in two flavours – internal and external functions.

Internal functions contain the actual code of the function. They can only be called inside the current contract and can only be executed inside the current contract context. Calling an internal function is similar to calling any other function that is defined in the current contract. The advantage of using Internal function type is that they can be passed around and invoked based on the application logic.

External functions contains the address and the function signature. These types can be used, as the name indicates, to execute the external functions.

Arrays

Arrays can be fixed size or dynamic at the compile time. The fixed size arrays are declared as T[k] where k is the fixed size of element T. The dynamic arrays are declared as T[]. The Array data type is similar to arrays in C# and other programming language.

Solidity support multi-dimensional array and this multi-dimensional array is declared as T[][]. We can even declare an array of dynamic arrays. For example to declare an array of 5 dynamic arrays, T[][5].

Array data type supports the following two members:
  • length: The length member holds and returns the number of elements in the array.
  • push: For dynamic storage arrays and bytes, push can be used to append an element at the end of the array. The function returns the new length of the array

Structs

Structs let us define complex data types or user defined data types in solidity. These structs are similar to other programming languages like C#. In our contract we will define a bidder type which holds the information of the contractor and his bid amount.

// struct type to hold bidder information
struct Bidder {
    address contractor;
    uint bidAmount;
}

Mappings

Mapping data types are the dynamic array of key value pair. Mappings are similar to hash table or dictionary in C# or other programming languages. Solidity uses SHA-3 hash (keccak256) on the key and stores the value with that hash. When needed it will use this hash to look up and retrieve the value.

mapping(address => Bidder) bids; // storing all bids received for the contract

Mappings are only allowed for state variables. Hence mappings typically used to data for quick retrieval.

Standalone PC to Decentralized Ethereum Platform


Early 1980s witnessed the beginning of a new era in computing owing to the birth of the general purpose personal computers. This PC technology penetrated homes, small business and schools.  At that time most of these computers are standalone and worked independently.

Slowly these independent computers had to connect to other independent computers to share data and resources. Computer networks which already existed at that time allowed these independent computers, sometimes called as nodes, to connect and share resources. As technology progressed the demand to connect more and more computers grew tremendously.

Early 1990 marks the transition of these smaller computer networks into a global system of interconnected computer networks. Thus giving birth to Internet. The Internet, sometimes called “Net”, is a massive network of networks that consists private, public, academic, business and government networks. Internet revolutionized how we exchange data between millions of computers. With computers spread across the globe forming a global infrastructure, Internet is the beginning of decentralized computing. No one owns Internet, and no single person or organization controls the Internet.

With increase in sharing between nodes or computers, a new communication protocol, BitTorrent, has evolved which enabled distribution of large data and files over the Internet. BitTorrent is the communication protocol for peer to peer file sharing (“P2P”) digital media using peer to peer networking technology. It relies decentralized network to effectively share resources and reduce burden on the centralized server. The decentralization technology continued to evolve.

With the advent of cloud, the environment changed drastically. All of a sudden a centralized computing took the prime seat. More and more servers were deployed on to the centralized cloud environment to perform computing, sharing resources etc.  The cloud revolution temporarily pushed the decentralized journey to back seat.

Bitcoin brought decentralization back to the table. It also revolutionized decentralized technologies with a decentralized peer to peer ledger that runs in a trustless public environment with immutable data and without any trusted central authority. It also introduced distributed consensus which helps all the nodes to validate the block and build the best block chain. Bitcoin uses Blockchain as the underlying technology.

Ethereum took this decentralized blockchain further by providing a platform where we can develop decentralized applications. Ethereum, sometimes called Blockchain 2.0, provides us a programming model which enables developers to write smart contracts that encapsulate user obligations in a decentralized network.


As you see the decentralization evolved from standalone systems to the current state and it will evolve further to become an efficient system with millions of transactions and capable of changing the technology we know.

Structure of an Ethereum Smart Contract

Smart Contract is similar to a class in object oriented programming. A smart contract can contain the following parts:
  • Version Pragma
  • Comments
  • State Variables
  • Functions
  • Function Modifiers
  • Events
  • Structs Types
  • Enums Types

Below is the brief definition of these components. In the subsequent blogs I will go in depth into each of these components:

Version Pragma

This pragma directive tells the compiler to use the correction version to compile the contract and to reject compiling with an incompatible compiler. This annotation ensures that our code is always compiled correctly as we intended.

The version pragma is used as follows:

pragma solidity ^0.4.14;

This directive is optional, but is highly recommended to annotate every source file with this version pragma. The version pragma uses semantic versioning and is denoted by [major, minor, patch] tuple. As shown above 0.4.14.

In the above version directive we used caret range to specify the supported compilers. The caret range allows compiler greater than the specified version and does not allow compiler greater than the left most non-zero digit. In our definition the left most non-zero digit is 4 (0.4). So the caret range allows compiler greater than the specified version (0.4.14) and does not allow greater than the left most non-zero digit (0.5.0). In other words, only compiler with version >= 0.4.14 and < 0.5.0 be allowed to compile to compile our contract code. This version pragma directive can also include prerelease tags such as alpha, beta. Below are examples of caret ranges:
  • ^0.4.14 := >=0.4.14 and <0.5.0
  • ^1.2.3 := >=1.2.3 and <2.0.0
  • ^0.2.3 := >=0.2.3 <0.3.0
  • ^0.0.3 := >=0.0.3 <0.0.4

The solidity compiler can use complex rules for identifying the correct compiler version. But this may be rarely used. Unless you want to target a specific version range, you don’t need to go that complex.

State Variables

State Variables are values which are permanently stored in contract storage. These are similar to the class variables.

pragma solidity ^0.4.14;

contract Service {
    address client; // State variable to store client who requests service
    address contractor; // State variable to store contractor for the service
    address platform; // State variable to store 0x address
}

In the above contract we defined three state variables called client, contractor and platform which are of type address. We use these variable to store the address of the client who requested service, contractor who has hired to perform the service and 0x platform who facilitates the interaction between client and contractor. I will revisit State Variables once we cover more details.

Functions

Functions are the executable units of code within a contract. Again these are similar to the functions in the object oriented world.

A contract can have the following types of functions
  • Member functions
  • Constructor
  • Fallback function
  • Constant functions

Member functions
These are the functions which modify the state variables of the contract and performs transactions that are stored in the block chain. These functions typically don’t have return values.

// hiring the contractor to perform the work
function hire (address _contractor) {
    contractor = _contractor;
}

In the above code the client of the service requestor finalized the contractor and is hiring the contractor to perform the service. As you see this function is updating the contractor state variable.

Constructor
A constructor is a special type of member function. The constructor is called only once for the life of the contract and during the initialization of the contract. Hence you can have all your initialization logic in this constructor. As show below I am storing the client address, one who creates the contract (msg.sender is the account which initializes the contract) and the 0x platform address which can be used to arbitrage between client and contractor.

// creates the service for the client
// 0x will be platform provider
function Service (address _platform) {
    client = msg.sender;
    platform = _platform;
} 

Fallback function
Fallback function is a function which does not have a function name. This function is invoked whenever a contact is called with a function name that does not exist. For example if user calls a function called “close” and this close function does not exist in the contract, then the fallback function will be called. In our code we don’t want users to call functions that don’t exist, hence reverting the call.

//default function
function() {
    revert();
}   

A contract can have exactly one unnamed function. This function cannot have arguments and cannot return anything. 

Constant function
A constant function is used in scenarios where you want to read the state variables of the contract and don’t want to update their state. Constant functions prevent updating the state variables of the contract. In our 0x contract we will have a validate function which checks the terms and conditions of our smart contract. For this POC the actual validation is out of scope. So let’s assume that the validation is always successful and return true as shown below:

// validate the terms of the contract
function validate() constant returns (bool) {
    // for POC we are doing additional validations
    return true;
} 

Function Modifiers
Function Modifiers are used to amend the semantics of a function in a declarative way. These can be used to automatically check a condition prior and/or after the execution of a function. Here is an example on how Function Modifiers are used in our 0x service contract

// modifier to ensure client can only execute a function
modifier onlyClient() {
    require(msg.sender == client);
    _;
}

function hire (address _contractor) onlyClient { // using function modifier
    contractor = _contractor;
}

In the above code we defined a function modifier, onlyClient, in which we are checking whether the caller of the contract function is a client. msg.sender contains the address of the caller. Require checks and validates the condition is true before proceeding. If the condition fails, requires throws an exception and exits the function.

The special symbol underscore “_” is very important in the modifier. The body of the actual function will be inserted and executed at this point. This enables us to use function modifiers before and/or after the execution of the function.

A function can have multiple function modifiers. These modifiers should be specified in a whitespace separated list and these modifiers are evaluated in the order present.

Structs Type

Structs are the custom defined types in Solidity. These are used to group several variables. In our 0x service we will be defining a custom type, struct, Bidder as shown below:

// struct type to hold bidder information
struct Bidder {
    address contractor;
    uint bidAmount;
}
mapping(address => Bidder) bids;

Struct types are typically used inside mappings and arrays. Mapping type in the above code is similar to the dictionary in C#. Structs can contain other structs and other complex types.

Enum Types

Enums are also user defined types in solidity (similar to structs). Enum Types will have a finite set of values. In our 0x Service contract we defined an enum to hold the current state of the contract as shown below:

enum State { Bid, Award, Work, Paid }
State contractState;


In the above code the State enum contains the possible states of the contract, i.e., open for bid, contract awarded, work started and finally payment for the service. contractState variable is used to store the current state of the contract.

Ethereum Solidity Compiler

Ethereum contracts are written in the high level language called Solidity and compiled into bytecode using the Solidity compiler. This ...