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.

Functions - Structure of an Ethereum Smart Contract


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
  • Default 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;
} 

Default function

Default 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 default function will be called. In our code we don’t want users to call functions that don’t exist, hence throwing an exception.

//default function
function() {
    throw;
}   

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;
}

This blog is part of Structure of an Ethereum Smart Contract, please refer to it for more details.

Version Pragma - Structure of an Ethereum Smart Contract

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.

This blog is part of Structure of an Ethereum Smart Contract, please refer to it for more details.

Ethereum Mist supersedes Wallet


Ethereum Mist now replaces the Ethereum Wallet. Here is the Ethereum wiki on wallet:

“Ethereum Wallet is just a Mist implementation enabled to access a single dapp – the wallet dapp, this is due to missing features in Mist itself and so that we are able to release earlier. So the wallet is Mist, in wallet mode”

As you see Ethereum Wallet is a stop gap solution while Mist is being built out. With Mist is getting ready for production release, we may as well be using Mist instead of Wallet.

Mist is a cross platform hybrid desktop application using web interface. It is built with electron. It will be easy for the web developers to debug using the Mist browser.


Ethereum Mist Browser with private chain


You can connect Ethereum Mist browser to the private chain and take advantages of the mist features. Here are the simple 2 steps to connect the mist browser to the private chain:
  • Start the private chain. Refer to my blog Ethereum Dev Chain - Private Chain for more details.
  • Run the Mist. It automatically connects to the private chain that is running on the same machine

That’s all. Now we can have the mist connected to the test chain as shown below:

Please note that on the windows machine, I had to run the geth and mist with administrative permissions


Ethereum Solidity Compiler

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