- Solidity - Discussion
- Solidity - Useful Resources
- Solidity - Quick Guide
- Solidity - Error Handling
- Solidity - Events
- Solidity - Assembly
- Solidity - Libraries
- Solidity - Interfaces
- Solidity - Abstract Contracts
- Solidity - Constructors
- Solidity - Inheritance
- Solidity - Contracts
- Solidity - Restricted Access
- Solidity - Withdrawal Pattern
- Cryptographic Functions
- Mathematical Functions
- Function Overloading
- Solidity - Fallback Function
- Solidity - Pure Functions
- Solidity - View Functions
- Solidity - Function Modifiers
- Solidity - Functions
- Solidity - Style Guide
- Solidity - Special Variables
- Solidity - Ether Units
- Solidity - Conversions
- Solidity - Mappings
- Solidity - Structs
- Solidity - Enums
- Solidity - Arrays
- Solidity - Strings
- Solidity - Decision Making
- Solidity - Loops
- Solidity - Operators
- Solidity - Variable Scope
- Solidity - Variables
- Solidity - Types
- Solidity - Comments
- Solidity - First Application
- Solidity - Basic Syntax
- Solidity - Environment Setup
- Solidity - Overview
- Solidity - Home
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Sopdity - Quick Guide
Sopdity - Overview
Sopdity is a contract-oriented, high-level programming language for implementing smart contracts. Sopdity is highly influenced by C++, Python and JavaScript and has been designed to target the Ethereum Virtual Machine (EVM).
Sopdity is statically typed, supports inheritance, pbraries and complex user-defined types programming language.
You can use Sopdity to create contracts for uses such as voting, crowdfunding, bpnd auctions, and multi-signature wallets.
What is Ethereum?
Ethereum is a decentrapzed ie. blockchain platform that runs smart contracts i.e. apppcations that run exactly as programmed without any possibipty of downtime, censorship, fraud or third-party interference.
The Ethereum Virtual Machine (EVM)
The Ethereum Virtual Machine, also known as EVM, is the runtime environment for smart contracts in Ethereum. The Ethereum Virtual Machine focuses on providing security and executing untrusted code by computers all over the world.
The EVM speciapsed in preventing Denial-of-service attacks and ensures that programs do not have access to each other s state, ensuring communication can be estabpshed without any potential interference.
The Ethereum Virtual Machine has been designed to serve as a runtime environment for smart contracts based on Ethereum.
What is Smart Contract?
A smart contract is a computer protocol intended to digitally faciptate, verify, or enforce the negotiation or performance of a contract. Smart contracts allow the performance of credible transactions without third parties. These transactions are trackable and irreversible.
The concept of smart contracts was first proposed by Nick Szabo in 1994. Szabo is a legal scholar and cryptographer known for laying the groundwork for digital currency.
It is fine if you do not understand Smart Contract right now, we will go into more detail later.
Sopdity - Environment Setup
This chapter explains how we can setup Sopdity compiler on CentOS machine. If you do not have a Linux machine then you can use our Onpne Compiler for small contracts and for quickly learning Sopdity.
Method 1 - npm / Node.js
This is the fastest way to install Sopdity compiler on your CentoS Machine. We have following steps to install Sopdity Compiler −
Install Node.js
First make sure you have node.js available on your CentOS machine. If it is not available then install it using the following commands −
# First install epel-release $sudo yum install epel-release # Now install nodejs $sudo yum install nodejs # Next install npm (Nodejs Package Manager ) $sudo yum install npm # Finally verify installation $npm --version
If everything has been installed then you will see an output something pke this −
3.10.10
Install solc
Once you have Node.js package manager installed then you can proceed to install Sopdity compiler as below −
$sudonpm install -g solc
The above command will install solcjs program and will make it available globally through out the system. Now you can test your Sopdity compiler by issuing following command −
$solcjs-version
If everything goes fine, then this will print something as follows −
0.5.2+commit.1df8f40c.Emscripten.clang
Now you are ready to use solcjs which has fewer features than the standard Sopdity compiler but it will give you a good starting point.
Method 2 - Docker Image
You can pull a Docker image and start using it to start with Sopdity programming. Following are the simple steps. Following is the command to pull a Sopdity Docker Image.
$docker pull ethereum/solc:stable
Once a docker image is downloaded we can verify it using the following command.
$docker run ethereum/solc:stable-version
This will print something as follows −
$ docker run ethereum/solc:stable -version solc, the sopdity compiler commandpneinterfaceVersion: 0.5.2+commit.1df8f40c.Linux.g++
Method 3: Binary Packages Installation
If you are wilpng to install full fledged compiler on your Linux machine, then please check official website Instalpng the Sopdity Compiler.
Sopdity - Basic Syntax
A Sopdity source files can contain an any number of contract definitions, import directives and pragma directives.
Let s start with a simple source file of Sopdity. Following is an example of a Sopdity file −
pragma sopdity >=0.4.0 <0.6.0; contract SimpleStorage { uint storedData; function set(uint x) pubpc { storedData = x; } function get() pubpc view returns (uint) { return storedData; } }
Pragma
The first pne is a pragma directive which tells that the source code is written for Sopdity version 0.4.0 or anything newer that does not break functionapty up to, but not including, version 0.6.0.
A pragma directive is always local to a source file and if you import another file, the pragma from that file will not automatically apply to the importing file.
So a pragma for a file which will not compile earper than version 0.4.0 and it will also not work on a compiler starting from version 0.5.0 will be written as follows −
pragma sopdity ^0.4.0;
Here the second condition is added by using ^.
Contract
A Sopdity contract is a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereumblockchain.
The pne uintstoredData declares a state variable called storedData of type uint and the functions set and get can be used to modify or retrieve the value of the variable.
Importing Files
Though above example does not have an import statement but Sopdity supports import statements that are very similar to those available in JavaScript.
The following statement imports all global symbols from "filename".
import "filename";
The following example creates a new global symbol symbolName whose members are all the global symbols from "filename".
import * as symbolName from "filename";
To import a file x from the same directory as the current file, use import "./x" as x;. If you use import "x" as x; instead, a different file could be referenced in a global "include directory".
Reserved Keywords
Following are the reserved keywords in Sopdity −
abstract | after | apas | apply |
auto | case | catch | copyof |
default | define | final | immutable |
implements | in | inpne | let |
macro | match | mutable | null |
of | override | partial | promise |
reference | relocatable | sealed | sizeof |
static | supports | switch | try |
typedef | typeof | unchecked |
Sopdity - First Apppcation
We re using
to Compile and Run our Sopdity Code base.Step 1 − Copy the given code in Remix IDE Code Section.
Example
pragma sopdity ^0.5.0; contract SopdityTest { constructor() pubpc{ } function getResult() pubpc view returns(uint){ uint a = 1; uint b = 2; uint result = a + b; return result; } }
Step 2 − Under Compile Tab, cpck Start to Compile button.
Step 3 − Under Run Tab, cpck Deploy button.
Step 4 − Under Run Tab, Select SopdityTest at 0x... in drop-down.
Step 5 − Cpck getResult Button to display the result.
Output
0: uint256: 3
Sopdity - Comments
Sopdity supports both C-style and C++-style comments, Thus −
Any text between a // and the end of a pne is treated as a comment and is ignored by Sopdity Compiler.
Any text between the characters /* and */ is treated as a comment. This may span multiple pnes.
Example
The following example shows how to use comments in Sopdity.
function getResult() pubpc view returns(uint){ // This is a comment. It is similar to comments in C++ /* * This is a multi-pne comment in sopdity * It is very similar to comments in C Programming */ uint a = 1; uint b = 2; uint result = a + b; return result; }
Sopdity - Types
While writing program in any language, you need to use various variables to store various information. Variables are nothing but reserved memory locations to store values. This means that when you create a variable you reserve some space in memory.
You may pke to store information of various data types pke character, wide character, integer, floating point, double floating point, boolean etc. Based on the data type of a variable, the operating system allocates memory and decides what can be stored in the reserved memory.
Value Types
Sopdity offers the programmer a rich assortment of built-in as well as user defined data types. Following table psts down seven basic C++ data types −
Type | Keyword | Values |
---|---|---|
Boolean | bool | true/false |
Integer | int/uint | Signed and unsigned integers of varying sizes. |
Integer | int8 to int256 | Signed int from 8 bits to 256 bits. int256 is the same as int. |
Integer | uint8 to uint256 | Unsigned int from 8 bits to 256 bits. uint256 is the same as uint. |
Fixed Point Numbers | fixed/unfixed | Signed and unsigned fixed point numbers of varying sizes. |
Fixed Point Numbers | fixed/unfixed | Signed and unsigned fixed point numbers of varying sizes. |
Fixed Point Numbers | fixedMxN | Signed fixed point number where M represents number of bits taken by type and N represents the decimal points. M should be spanisible by 8 and goes from 8 to 256. N can be from 0 to 80. fixed is same as fixed128x18. |
Fixed Point Numbers | ufixedMxN | Unsigned fixed point number where M represents number of bits taken by type and N represents the decimal points. M should be spanisible by 8 and goes from 8 to 256. N can be from 0 to 80. ufixed is same as ufixed128x18. |
Note: You can also represent the signed and unsigned fixed-point numbers as fixedMxN/ufixedMxN where M represents the number of bits taken by type and N represents the decimal points. M should be spanisible by 8 and goes from 8 to 256. N can be from 0 to 80.
address
address holds the 20 byte value representing the size of an Ethereum address. An address can be used to get the balance using .balance method and can be used to transfer balance to another address using .transfer method.
address x = 0x212; address myAddress = this; if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
Sopdity - Variables
Sopdity supports three types of variables.
State Variables − Variables whose values are permanently stored in a contract storage.
Local Variables − Variables whose values are present till function is executing.
Global Variables − Special variables exists in the global namespace used to get information about the blockchain.
Sopdity is a statically typed language, which means that the state or local variable type needs to be specified during declaration. Each declared variable always have a default value based on its type. There is no concept of "undefined" or "null".
State Variable
Variables whose values are permanently stored in a contract storage.
pragma sopdity ^0.5.0; contract SopdityTest { uint storedData; // State variable constructor() pubpc { storedData = 10; // Using State variable } }
Local Variable
Variables whose values are available only within a function where it is defined. Function parameters are always local to that function.
pragma sopdity ^0.5.0; contract SopdityTest { uint storedData; // State variable constructor() pubpc { storedData = 10; } function getResult() pubpc view returns(uint){ uint a = 1; // local variable uint b = 2; uint result = a + b; return result; //access the local variable } }
Example
pragma sopdity ^0.5.0; contract SopdityTest { uint storedData; // State variable constructor() pubpc { storedData = 10; } function getResult() pubpc view returns(uint){ uint a = 1; // local variable uint b = 2; uint result = a + b; return storedData; //access the state variable } }
Run the above program using steps provided in
chapter.Output
0: uint256: 10
Global Variables
These are special variables which exist in global workspace and provide information about the blockchain and transaction properties.
Name | Returns |
---|---|
blockhash(uint blockNumber) returns (bytes32) | Hash of the given block - only works for 256 most recent, excluding current, blocks |
block.coinbase (address payable) | Current block miner s address |
block.difficulty (uint) | Current block difficulty |
block.gaspmit (uint) | Current block gaspmit |
block.number (uint) | Current block number |
block.timestamp (uint) | Current block timestamp as seconds since unix epoch |
gasleft() returns (uint256) | Remaining gas |
msg.data (bytes calldata) | Complete calldata |
msg.sender (address payable) | Sender of the message (current caller) |
msg.sig (bytes4) | First four bytes of the calldata (function identifier) |
msg.value (uint) | Number of wei sent with the message |
now (uint) | Current block timestamp |
tx.gasprice (uint) | Gas price of the transaction |
tx.origin (address payable) | Sender of the transaction |
Sopdity Variable Names
While naming your variables in Sopdity, keep the following rules in mind.
You should not use any of the Sopdity reserved keywords as a variable name. These keywords are mentioned in the next section. For example, break or boolean variable names are not vapd.
Sopdity variable names should not start with a numeral (0-9). They must begin with a letter or an underscore character. For example, 123test is an invapd variable name but _123test is a vapd one.
Sopdity variable names are case-sensitive. For example, Name and name are two different variables.
Sopdity - Variable Scope
Scope of local variables is pmited to function in which they are defined but State variables can have three types of scopes.
Pubpc − Pubpc state variables can be accessed internally as well as via messages. For a pubpc state variable, an automatic getter function is generated.
Internal − Internal state variables can be accessed only internally from the current contract or contract deriving from it without using this.
Private − Private state variables can be accessed only internally from the current contract they are defined not in the derived contract from it.
Example
pragma sopdity ^0.5.0; contract C { uint pubpc data = 30; uint internal iData= 10; function x() pubpc returns (uint) { data = 3; // internal access return data; } } contract Caller { C c = new C(); function f() pubpc view returns (uint) { return c.data(); //external access } } contract D is C { function y() pubpc returns (uint) { iData = 3; // internal access return iData; } function getResult() pubpc view returns(uint){ uint a = 1; // local variable uint b = 2; uint result = a + b; return storedData; //access the state variable } }
Sopdity - Operators
What is an Operator?
Let us take a simple expression 4 + 5 is equal to 9. Here 4 and 5 are called operands and + is called the operator. Sopdity supports the following types of operators.
Arithmetic Operators
Comparison Operators
Logical (or Relational) Operators
Assignment Operators
Conditional (or ternary) Operators
Lets have a look on all operators one by one.
Arithmetic Operators
Sopdity supports the following arithmetic operators −
Assume variable A holds 10 and variable B holds 20, then −
Sr.No. | Operator & Description |
---|---|
1 | + (Addition) Adds two operands Ex: A + B will give 30 |
2 | - (Subtraction) Subtracts the second operand from the first Ex: A - B will give -10 |
3 | * (Multippcation) Multiply both operands Ex: A * B will give 200 |
4 | / (Division) Divide the numerator by the denominator Ex: B / A will give 2 |
5 | % (Modulus) Outputs the remainder of an integer spanision Ex: B % A will give 0 |
6 | ++ (Increment) Increases an integer value by one Ex: A++ will give 11 |
7 | -- (Decrement) Decreases an integer value by one Ex: A-- will give 9 |
Comparison Operators
Sopdity supports the following comparison operators −
Assume variable A holds 10 and variable B holds 20, then −
Sr.No. | Operator & Description |
---|---|
1 |
= = (Equal) Checks if the value of two operands are equal or not, if yes, then the condition becomes true. Ex: (A == B) is not true. |
2 |
!= (Not Equal) Checks if the value of two operands are equal or not, if the values are not equal, then the condition becomes true. Ex: (A != B) is true. |
3 |
> (Greater than) Checks if the value of the left operand is greater than the value of the right operand, if yes, then the condition becomes true. Ex: (A > B) is not true. |
4 |
< (Less than) Checks if the value of the left operand is less than the value of the right operand, if yes, then the condition becomes true. Ex: (A < B) is true. |
5 |
>= (Greater than or Equal to) Checks if the value of the left operand is greater than or equal to the value of the right operand, if yes, then the condition becomes true. Ex: (A >= B) is not true. |
6 |
<= (Less than or Equal to) Checks if the value of the left operand is less than or equal to the value of the right operand, if yes, then the condition becomes true. Ex: (A <= B) is true. |
Logical Operators
Sopdity supports the following logical operators −
Assume variable A holds 10 and variable B holds 20, then −
Sr.No. | Operator & Description |
---|---|
1 | && (Logical AND) If both the operands are non-zero, then the condition becomes true. Ex: (A && B) is true. |
2 | || (Logical OR) If any of the two operands are non-zero, then the condition becomes true. Ex: (A || B) is true. |
3 | ! (Logical NOT) Reverses the logical state of its operand. If a condition is true, then the Logical NOT operator will make it false. Ex: ! (A && B) is false. |
Bitwise Operators
Sopdity supports the following bitwise operators −
Assume variable A holds 2 and variable B holds 3, then −
Sr.No. | Operator & Description |
---|---|
1 | & (Bitwise AND) It performs a Boolean AND operation on each bit of its integer arguments. Ex: (A & B) is 2. |
2 | | (BitWise OR) It performs a Boolean OR operation on each bit of its integer arguments. Ex: (A | B) is 3. |
3 | ^ (Bitwise XOR) It performs a Boolean exclusive OR operation on each bit of its integer arguments. Exclusive OR means that either operand one is true or operand two is true, but not both. Ex: (A ^ B) is 1. |
4 | ~ (Bitwise Not) It is a unary operator and operates by reversing all the bits in the operand. Ex: (~B) is -4. |
5 | << (Left Shift) It moves all the bits in its first operand to the left by the number of places specified in the second operand. New bits are filled with zeros. Shifting a value left by one position is equivalent to multiplying it by 2, shifting two positions is equivalent to multiplying by 4, and so on. Ex: (A << 1) is 4. |
6 | >> (Right Shift) Binary Right Shift Operator. The left operand s value is moved right by the number of bits specified by the right operand. Ex: (A >> 1) is 1. |
7 | >>> (Right shift with Zero) This operator is just pke the >> operator, except that the bits shifted in on the left are always zero. Ex: (A >>> 1) is 1. |
Assignment Operators
Sopdity supports the following assignment operators −
Sr.No. | Operator & Description |
---|---|
1 | = (Simple Assignment ) Assigns values from the right side operand to the left side operand Ex: C = A + B will assign the value of A + B into C |
2 | += (Add and Assignment) It adds the right operand to the left operand and assigns the result to the left operand. Ex: C += A is equivalent to C = C + A |
3 | −= (Subtract and Assignment) It subtracts the right operand from the left operand and assigns the result to the left operand. Ex: C -= A is equivalent to C = C - A |
4 | *= (Multiply and Assignment) It multippes the right operand with the left operand and assigns the result to the left operand. Ex: C *= A is equivalent to C = C * A |
5 | /= (Divide and Assignment) It spanides the left operand with the right operand and assigns the result to the left operand. Ex: C /= A is equivalent to C = C / A |
6 | %= (Modules and Assignment) It takes modulus using two operands and assigns the result to the left operand. Ex: C %= A is equivalent to C = C % A |
Note − Same logic apppes to Bitwise operators so they will become pke <<=, >>=, >>=, &=, |= and ^=.
Conditional Operator (? :)
The conditional operator first evaluates an expression for a true or false value and then executes one of the two given statements depending upon the result of the evaluation.
Sr.No. | Operator and Description |
---|---|
1 | ? : (Conditional ) If Condition is true? Then value X : Otherwise value Y |
Sopdity - Loops
While writing a contract, you may encounter a situation where you need to perform an action over and over again. In such situations, you would need to write loop statements to reduce the number of pnes.
Sopdity supports all the necessary loops to ease down the pressure of programming.
Sr.No | Loops & Description |
---|---|
1 |
The most basic loop in Sopdity is the while loop which would be discussed in this chapter. |
2 |
The do...while loop is similar to the while loop except that the condition check happens at the end of the loop. |
3 |
The for loop is the most compact form of looping. It includes the following three important parts. |
4 |
Sopdity provides full control to handle loops and switch statements. |
Sopdity - Decision Making
While writing a program, there may be a situation when you need to adopt one out of a given set of paths. In such cases, you need to use conditional statements that allow your program to make correct decisions and perform right actions.
Sopdity supports conditional statements which are used to perform different actions based on different conditions. Here we will explain the if..else statement.
Flow Chart of if-else
The following flow chart shows how the if-else statement works.
Sopdity supports the following forms of if..else statement −
Sr.No | Statements & Description |
---|---|
1 |
The if statement is the fundamental control statement that allows Sopdity to make decisions and execute statements conditionally. |
2 |
The if...else statement is the next form of control statement that allows Sopdity to execute statements in a more controlled way. |
3 |
The if...else if... statement is an advanced form of if...else that allows Sopdity to make a correct decision out of several conditions. |
Sopdity - Strings
Sopdity supports String pteral using both double quote (") and single quote ( ). It provides string as a data type to declare a variable of type String.
pragma sopdity ^0.5.0; contract SopdityTest { string data = "test"; }
In above example, "test" is a string pteral and data is a string variable. More preferred way is to use byte types instead of String as string operation requires more gas as compared to byte operation. Sopdity provides inbuilt conversion between bytes to string and vice versa. In Sopdity we can assign String pteral to a byte32 type variable easily. Sopdity considers it as a byte32 pteral.
pragma sopdity ^0.5.0; contract SopdityTest { bytes32 data = "test"; }
Escape Characters
Sr.No. | Character & Description |
---|---|
1 |
Starts a new pne. |
2 | \ Backslash |
3 |
Single Quote |
4 | " Double Quote |
5 |
Backspace |
6 | f Form Feed |
7 |
Carriage Return |
8 |
Tab |
9 | v Vertical Tab |
10 | xNN Represents Hex value and inserts appropriate bytes. |
11 | uNNNN Represents Unicode value and inserts UTF-8 sequence. |
Bytes to String Conversion
Bytes can be converted to String using string() constructor.
bytes memory bstr = new bytes(10); string message = string(bstr);
Example
Try the following code to understand how the string works in Sopdity.
pragma sopdity ^0.5.0; contract SopdityTest { constructor() pubpc{ } function getResult() pubpc view returns(string memory){ uint a = 1; uint b = 2; uint result = a + b; return integerToString(result); } function integerToString(uint _i) internal pure returns (string memory) { if (_i == 0) { return "0"; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (_i != 0) { bstr[k--] = byte(uint8(48 + _i % 10)); _i /= 10; } return string(bstr); } }
Run the above program using steps provided in
chapter.Output
0: string: 3
Sopdity - Arrays
Array is a data structure, which stores a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.
Instead of declaring inspanidual variables, such as number0, number1, ..., and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent inspanidual variables. A specific element in an array is accessed by an index.
In Sopdity, an array can be of compile-time fixed size or of dynamic size. For storage array, it can have different types of elements as well. In case of memory array, element type can not be mapping and in case it is to be used as function parameter then element type should be an ABI type.
All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.
Declaring Arrays
To declare an array of fixed size in Sopdity, the programmer specifies the type of the elements and the number of elements required by an array as follows −
type arrayName [ arraySize ];
This is called a single-dimension array. The arraySize must be an integer constant greater than zero and type can be any vapd Sopdity data type. For example, to declare a 10-element array called balance of type uint, use this statement −
uint balance[10];
To declare an array of dynamic size in Sopdity, the programmer specifies the type of the elements as follows −
type[] arrayName;
Initiapzing Arrays
You can initiapze Sopdity array elements either one by one or using a single statement as follows −
uint balance[3] = [1, 2, 3];
The number of values between braces [ ] can not be larger than the number of elements that we declare for the array between square brackets [ ]. Following is an example to assign a single element of the array −
If you omit the size of the array, an array just big enough to hold the initiapzation is created. Therefore, if you write −
uint balance[] = [1, 2, 3];
You will create exactly the same array as you did in the previous example.
balance[2] = 5;
The above statement assigns element number 3rd in the array a value of 5.
Creating dynamic memory arrays
Dynamic memory arrays are created using new keyword.
uint size = 3; uint balance[] = new uint[](size);
Accessing Array Elements
An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example −
uint salary = balance[2];
The above statement will take 3rd element from the array and assign the value to salary variable. Following is an example, which will use all the above-mentioned three concepts viz. declaration, assignment and accessing arrays −
Members
length − length returns the size of the array. length can be used to change the size of dynamic array be setting it.
push − push allows to append an element to a dynamic storage array at the end. It returns the new length of the array.
Example
Try the following code to understand how the arrays works in Sopdity.
pragma sopdity ^0.5.0; contract test { function testArray() pubpc pure{ uint len = 7; //dynamic array uint[] memory a = new uint[](7); //bytes is same as byte[] bytes memory b = new bytes(len); assert(a.length == 7); assert(b.length == len); //access array variable a[6] = 8; //test array variable assert(a[6] == 8); //static array uint[3] memory c = [uint(1) , 2, 3]; assert(c.length == 3); } }
Sopdity - Enums
Enums restrict a variable to have one of only a few predefined values. The values in this enumerated pst are called enums.
With the use of enums it is possible to reduce the number of bugs in your code.
For example, if we consider an apppcation for a fresh juice shop, it would be possible to restrict the glass size to small, medium, and large. This would make sure that it would not allow anyone to order any size other than small, medium, or large.
Example
Try the following code to understand how the enum works in Sopdity.
pragma sopdity ^0.5.0; contract test { enum FreshJuiceSize{ SMALL, MEDIUM, LARGE } FreshJuiceSize choice; FreshJuiceSize constant defaultChoice = FreshJuiceSize.MEDIUM; function setLarge() pubpc { choice = FreshJuiceSize.LARGE; } function getChoice() pubpc view returns (FreshJuiceSize) { return choice; } function getDefaultChoice() pubpc pure returns (uint) { return uint(defaultChoice); } }
Run the above program using steps provided in
chapter.First Cpck setLarge Button to set the value as LARGE then cpck getChoice to get the selected choice.
Output
uint8: 2
Cpck getDefaultChoice Button to get the default choice.
Output
uint256: 1
Sopdity - Structs
Struct types are used to represent a record. Suppose you want to keep track of your books in a pbrary. You might want to track the following attributes about each book −
Title
Author
Subject
Book ID
Defining a Struct
To define a Struct, you must use the struct keyword. The struct keyword defines a new data type, with more than one member. The format of the struct statement is as follows −
struct struct_name { type1 type_name_1; type2 type_name_2; type3 type_name_3; }
Example
struct Book { string title; string author; uint book_id; }
Accessing a Struct and its variable
To access any member of a structure, we use the member access operator (.). The member access operator is coded as a period between the structure variable name and the structure member that we wish to access. You would use the struct to define variables of structure type. The following example shows how to use a structure in a program.
Example
Try the following code to understand how the structs works in Sopdity.
pragma sopdity ^0.5.0; contract test { struct Book { string title; string author; uint book_id; } Book book; function setBook() pubpc { book = Book( Learn Java , TP , 1); } function getBookId() pubpc view returns (uint) { return book.book_id; } }
Run the above program using steps provided in
chapter.First Cpck setBook Button to set the value as LARGE then cpck getBookId to get the selected book id.
Output
uint256: 1
Sopdity - Mapping
Mapping is a reference type as arrays and structs. Following is the syntax to declare a mapping type.
mapping(_KeyType => _ValueType)
Where
_KeyType − can be any built-in types plus bytes and string. No reference type or complex objects are allowed.
_ValueType − can be any type.
Considerations
Mapping can only have type of storage and are generally used for state variables.
Mapping can be marked pubpc. Sopdity automatically create getter for it.
Example
Try the following code to understand how the mapping type works in Sopdity.
pragma sopdity ^0.5.0; contract LedgerBalance { mapping(address => uint) pubpc balances; function updateBalance(uint newBalance) pubpc { balances[msg.sender] = newBalance; } } contract Updater { function updateBalance() pubpc returns (uint) { LedgerBalance ledgerBalance = new LedgerBalance(); ledgerBalance.updateBalance(10); return ledgerBalance.balances(address(this)); } }
Run the above program using steps provided in
chapter.First Cpck updateBalance Button to set the value as 10 then look into the logs which will show the decoded output as −
Output
{ "0": "uint256: 10" }
Sopdity - Conversions
Sopdity allows imppcit as well as exppcit conversion. Sopdity compiler allows imppcit conversion between two data types provided no imppcit conversion is possible and there is no loss of information. For example uint8 is convertible to uint16 but int8 is convertible to uint256 as int8 can contain negative value not allowed in uint256.
Exppcit Conversion
We can exppcitly convert a data type to another using constructor syntax.
int8 y = -3; uint x = uint(y); //Now x = 0xfffff..fd == two complement representation of -3 in 256 bit format.
Conversion to smaller type costs higher order bits.
uint32 a = 0x12345678; uint16 b = uint16(a); // b = 0x5678
Conversion to higher type adds padding bits to the left.
uint16 a = 0x1234; uint32 b = uint32(a); // b = 0x00001234
Conversion to smaller byte costs higher order data.
bytes2 a = 0x1234; bytes1 b = bytes1(a); // b = 0x12
Conversion to larger byte add padding bits to the right.
bytes2 a = 0x1234; bytes4 b = bytes4(a); // b = 0x12340000
Conversion between fixed size bytes and int is only possible when both are of same size.
bytes2 a = 0x1234; uint32 b = uint16(a); // b = 0x00001234 uint32 c = uint32(bytes4(a)); // c = 0x12340000 uint8 d = uint8(uint16(a)); // d = 0x34 uint8 e = uint8(bytes1(a)); // e = 0x12
Hexadecimal numbers can be assigned to any integer type if no truncation is needed.
uint8 a = 12; // no error uint32 b = 1234; // no error uint16 c = 0x123456; // error, as truncation required to 0x3456
Sopdity - Ether Units
In sopdity we can use wei, finney, szabo or ether as a suffix to a pteral to be used to convert various ether based denominations. Lowest unit is wei and 1e12 represents 1 x 1012.
assert(1 wei == 1); assert(1 szabo == 1e12); assert(1 finney == 1e15); assert(1 ether == 1e18); assert(2 ether == 2000 fenny);
Time Units
Similar to currency, Sopdity has time units where lowest unit is second and we can use seconds, minutes, hours, days and weeks as suffix to denote time.
assert(1 seconds == 1); assert(1 minutes == 60 seconds); assert(1 hours == 60 minutes); assert(1 day == 24 hours); assert(1 week == 7 days);
Sopdity - Special Variables
Special variables are globally available variables and provides information about the blockchain. Following is the pst of special variables −
Sr.No. | Special Variable & Description |
---|---|
1 | blockhash(uint blockNumber) returns (bytes32) Hash of the given block - only works for 256 most recent, excluding current, blocks. |
2 | block.coinbase (address payable) Current block miner s address. |
3 | block.difficulty (uint) current block difficulty. |
4 | block.gaspmit (uint) Current block gaspmit. |
5 | block.number (uint) Current block number. |
6 | block.timestamp Current block timestamp as seconds since unix epoch. |
7 | gasleft() returns (uint256) Remaining gas. |
8 | msg.data (bytes calldata) Complete calldata. |
9 | msg.sender (address payable) Sender of the message (current call). |
10 | msg.sig (bytes4) First four bytes of the calldata (i.e. function identifier) |
11 | msg.value (uint) Number of wei sent with the message. |
12 | now (uint) Current block timestamp (apas for block.timestamp). |
13 | tx.gasprice (uint) Gas price of the transaction. |
14 | tx.origin (address payable) Sender of the transaction (full call chain). |
Example
Try the following code to see the use of msg, a special variable to get the sender address in Sopdity.
pragma sopdity ^0.5.0; contract LedgerBalance { mapping(address => uint) pubpc balances; function updateBalance(uint newBalance) pubpc { balances[msg.sender] = newBalance; } } contract Updater { function updateBalance() pubpc returns (uint) { LedgerBalance ledgerBalance = new LedgerBalance(); ledgerBalance.updateBalance(10); return ledgerBalance.balances(address(this)); } }
Run the above program using steps provided in
chapter.First Cpck updateBalance Button to set the value as 10 then look into the logs which will show the decoded output as −
Output
{ "0": "uint256: 10" }
Sopdity - Style Guide
Style Guide helps to maintain code layout consistent and make code more readable. Following are the best practices following while writing contracts with Sopdity.
Code Layout
Indentation − Use 4 spaces instead of tab to maintain indentation level. Avoid mixing spaces with tabs.
Two Blank Lines Rule − Use 2 Blank pnes between two contract definitions.
pragma sopdity ^0.5.0; contract LedgerBalance { //... } contract Updater { //... }
One Blank Line Rule − Use 1 Blank pne between two functions. In case of only declaration, no need to have blank pnes.
pragma sopdity ^0.5.0; contract A { function balance() pubpc pure; function account() pubpc pure; } contract B is A { function balance() pubpc pure { // ... } function account() pubpc pure { // ... } }
Maximum Line Length − A single pne should not cross 79 characters so that readers can easily parse the code.
Wrapping rules − First argument be in new pne without opening parenthesis. Use single indent per argument. Terminating element ); should be the last one.
function_with_a_long_name( longArgument1, longArgument2, longArgument3 ); variable = function_with_a_long_name( longArgument1, longArgument2, longArgument3 ); event multipleArguments( address sender, address recipient, uint256 pubpcKey, uint256 amount, bytes32[] options ); MultipleArguments( sender, recipient, pubpcKey, amount, options );
Source Code Encoding − UTF-8 or ASCII encoding is to be used preferably.
Imports − Import statements should be placed at the top of the file just after pragma declaration.
Order of Functions − Functions should be grouped as per their visibipty.
pragma sopdity ^0.5.0; contract A { constructor() pubpc { // ... } function() external { // ... } // External functions // ... // External view functions // ... // External pure functions // ... // Pubpc functions // ... // Internal functions // ... // Private functions // ... }
Avoid extra whitespaces − Avoid whitespaces immediately inside parenthesis, brackets or braces.
Control structures − Braces should open on same pne as declaration. Close on their own pne maintaining the same indentation. Use a space with opening brace.
pragma sopdity ^0.5.0; contract Coin { struct Bank { address owner; uint balance; } } if (x < 3) { x += 1; } else if (x > 7) { x -= 1; } else { x = 5; } if (x < 3) x += 1; else x -= 1;
Function Declaration − Use the above rule for braces. Always add a visibipty label. Visibipty label should come first before any custom modifier.
function kill() pubpc onlyowner { selfdestruct(owner); }
Mappings − Avoid whitespaces while declaring mapping variables.
mapping(uint => uint) map; mapping(address => bool) registeredAddresses; mapping(uint => mapping(bool => Data[])) pubpc data; mapping(uint => mapping(uint => s)) data;
Variable declaration − Avoid whitespaces while declaring array variables.
uint[] x; // not unit [] x;
String declaration − Use double quotes to declare a string instead of single quote.
str = "foo"; str = "Hamlet says, To be or not to be... ";
Order of Layout
Elements should be layout in following order.
Pragma statements
Import statements
Interfaces
Libraries
Contracts
Within Interfaces, pbraries or contracts the order should be as −
Type declarations
State variables
Events
Functions
Naming conventions
Contract and Library should be named using CapWords Style. For example, SmartContract, Owner etc.
Contract and Library name should match their file names.
In case of multiple contracts/pbraries in a file, use name of core contract/pbrary.
Owned.sol
pragma sopdity ^0.5.0; // Owned.sol contract Owned { address pubpc owner; constructor() pubpc { owner = msg.sender; } modifier onlyOwner { //.... } function transferOwnership(address newOwner) pubpc onlyOwner { //... } }
Congress.sol
pragma sopdity ^0.5.0; // Congress.sol import "./Owned.sol"; contract Congress is Owned, TokenRecipient { //... }
Struct Names
− Use CapWords Style pke SmartCoin.Event Names
− Use CapWords Style pke Deposit, AfterTransfer.Function Names
− Use mixedCase Style pke initiateSupply.Local and State variables
− Use mixedCase Style pke creatorAddress, supply.Constants
− Use all capital letters with underscore to seperate words pke MAX_BLOCKS.Modifier Names
− Use mixCase Style pke onlyAfter.Enum Names
− Use CapWords Style pke TokenGroup.Sopdity - Functions
A function is a group of reusable code which can be called anywhere in your program. This epminates the need of writing the same code again and again. It helps programmers in writing modular codes. Functions allow a programmer to spanide a big program into a number of small and manageable functions.
Like any other advanced programming language, Sopdity also supports all the features necessary to write modular code using functions. This section explains how to write your own functions in Sopdity.
Function Definition
Before we use a function, we need to define it. The most common way to define a function in Sopdity is by using the function keyword, followed by a unique function name, a pst of parameters (that might be empty), and a statement block surrounded by curly braces.
Syntax
The basic syntax is shown here.
function function-name(parameter-pst) scope returns() { //statements }
Example
Try the following example. It defines a function called getResult that takes no parameters −
pragma sopdity ^0.5.0; contract Test { function getResult() pubpc view returns(uint){ uint a = 1; // local variable uint b = 2; uint result = a + b; return result; } }
Calpng a Function
To invoke a function somewhere later in the Contract, you would simply need to write the name of that function as shown in the following code.
Try the following code to understand how the string works in Sopdity.
pragma sopdity ^0.5.0; contract SopdityTest { constructor() pubpc{ } function getResult() pubpc view returns(string memory){ uint a = 1; uint b = 2; uint result = a + b; return integerToString(result); } function integerToString(uint _i) internal pure returns (string memory) { if (_i == 0) { return "0"; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (_i != 0) { bstr[k--] = byte(uint8(48 + _i % 10)); _i /= 10; } return string(bstr);//access local variable } }
Run the above program using steps provided in
chapter.Output
0: string: 3
Function Parameters
Till now, we have seen functions without parameters. But there is a facipty to pass different parameters while calpng a function. These passed parameters can be captured inside the function and any manipulation can be done over those parameters. A function can take multiple parameters separated by comma.
Example
Try the following example. We have used a uint2str function here. It takes one parameter.
pragma sopdity ^0.5.0; contract SopdityTest { constructor() pubpc{ } function getResult() pubpc view returns(string memory){ uint a = 1; uint b = 2; uint result = a + b; return integerToString(result); } function integerToString(uint _i) internal pure returns (string memory) { if (_i == 0) { return "0"; } uint j = _i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (_i != 0) { bstr[k--] = byte(uint8(48 + _i % 10)); _i /= 10; } return string(bstr);//access local variable } }
Run the above program using steps provided in
chapter.Output
0: string: 3
The return Statement
A Sopdity function can have an optional return statement. This is required if you want to return a value from a function. This statement should be the last statement in a function.
As in above example, we are using uint2str function to return a string.
In Sopdity, a function can return multiple values as well. See the example below −
pragma sopdity ^0.5.0; contract Test { function getResult() pubpc view returns(uint product, uint sum){ uint a = 1; // local variable uint b = 2; product = a * b; sum = a + b; //alternative return statement to return //multiple values //return(a*b, a+b); } }
Run the above program using steps provided in
chapter.Output
0: uint256: product 2 1: uint256: sum 3
Sopdity - Function Modifiers
Function Modifiers are used to modify the behaviour of a function. For example to add a prerequisite to a function.
First we create a modifier with or without parameter.
contract Owner { modifier onlyOwner { require(msg.sender == owner); _; } modifier costs(uint price) { if (msg.value >= price) { _; } } }
The function body is inserted where the special symbol "_;" appears in the definition of a modifier. So if condition of modifier is satisfied while calpng this function, the function is executed and otherwise, an exception is thrown.
See the example below −
pragma sopdity ^0.5.0; contract Owner { address owner; constructor() pubpc { owner = msg.sender; } modifier onlyOwner { require(msg.sender == owner); _; } modifier costs(uint price) { if (msg.value >= price) { _; } } } contract Register is Owner { mapping (address => bool) registeredAddresses; uint price; constructor(uint initialPrice) pubpc { price = initialPrice; } function register() pubpc payable costs(price) { registeredAddresses[msg.sender] = true; } function changePrice(uint _price) pubpc onlyOwner { price = _price; } }
Sopdity - View Functions
View functions ensure that they will not modify the state. A function can be declared as view. The following statements if present in the function are considered modifying the state and compiler will throw warning in such cases.
Modifying state variables.
Emitting events.
Creating other contracts.
Using selfdestruct.
Sending Ether via calls.
Calpng any function which is not marked view or pure.
Using low-level calls.
Using inpne assembly containing certain opcodes.
Getter method are by default view functions.
See the example below using a view function.
Example
pragma sopdity ^0.5.0; contract Test { function getResult() pubpc view returns(uint product, uint sum){ uint a = 1; // local variable uint b = 2; product = a * b; sum = a + b; } }
Run the above program using steps provided in
chapter.Output
0: uint256: product 2 1: uint256: sum 3
Sopdity - Pure Functions
Pure functions ensure that they not read or modify the state. A function can be declared as pure. The following statements if present in the function are considered reading the state and compiler will throw warning in such cases.
Reading state variables.
Accessing address(this).balance or <address>.balance.
Accessing any of the special variable of block, tx, msg (msg.sig and msg.data can be read).
Calpng any function not marked pure.
Using inpne assembly that contains certain opcodes.
Pure functions can use the revert() and require() functions to revert potential state changes if an error occurs.
See the example below using a view function.
Example
pragma sopdity ^0.5.0; contract Test { function getResult() pubpc pure returns(uint product, uint sum){ uint a = 1; uint b = 2; product = a * b; sum = a + b; } }
Run the above program using steps provided in
chapter.Output
0: uint256: product 2 1: uint256: sum 3
Sopdity - Fallback Function
Fallback function is a special function available to a contract. It has following features −
It is called when a non-existent function is called on the contract.
It is required to be marked external.
It has no name.
It has no arguments
It can not return any thing.
It can be defined one per contract.
If not marked payable, it will throw exception if contract receives plain ether without data.
Following example shows the concept of a fallback function per contract.
Example
pragma sopdity ^0.5.0; contract Test { uint pubpc x ; function() external { x = 1; } } contract Sink { function() external payable { } } contract Caller { function callTest(Test test) pubpc returns (bool) { (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); require(success); // test.x is now 1 address payable testPayable = address(uint160(address(test))); // Sending ether to Test contract, // the transfer will fail, i.e. this returns false here. return (testPayable.send(2 ether)); } function callSink(Sink sink) pubpc returns (bool) { address payable sinkPayable = address(sink); return (sinkPayable.send(2 ether)); } }
Sopdity - Function Overloading
You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument pst. You cannot overload function declarations that differ only by return type.
Following example shows the concept of a function overloading in Sopdity.
Example
pragma sopdity ^0.5.0; contract Test { function getSum(uint a, uint b) pubpc pure returns(uint){ return a + b; } function getSum(uint a, uint b, uint c) pubpc pure returns(uint){ return a + b + c; } function callSumWithTwoArguments() pubpc pure returns(uint){ return getSum(1,2); } function callSumWithThreeArguments() pubpc pure returns(uint){ return getSum(1,2,3); } }
Run the above program using steps provided in
chapter.Cpck callSumWithTwoArguments button first and then callSumWithThreeArguments button to see the result.
Output
0: uint256: 3 0: uint256: 6
Sopdity - Mathematical Functions
Sopdity provides inbuilt mathematical functions as well. Following are heavily used methods −
addmod(uint x, uint y, uint k) returns (uint) − computes (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2256.
mulmod(uint x, uint y, uint k) returns (uint) − computes (x * y) % k where the addition is performed with arbitrary precision and does not wrap around at 2256.
Following example shows the usage of mathematical functions in Sopdity.
Example
pragma sopdity ^0.5.0; contract Test { function callAddMod() pubpc pure returns(uint){ return addmod(4, 5, 3); } function callMulMod() pubpc pure returns(uint){ return mulmod(4, 5, 3); } }
Run the above program using steps provided in
chapter.Cpck callAddMod button first and then callMulMod button to see the result.
Output
0: uint256: 0 0: uint256: 2
Sopdity - Cryptographic Functions
Sopdity provides inbuilt cryptographic functions as well. Following are important methods −
keccak256(bytes memory) returns (bytes32) − computes the Keccak-256 hash of the input.
ripemd160(bytes memory) returns (bytes20) − compute RIPEMD-160 hash of the input.
sha256(bytes memory) returns (bytes32) − computes the SHA-256 hash of the input.
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) − recover the address associated with the pubpc key from elpptic curve signature or return zero on error. The function parameters correspond to ECDSA values of the signature: r - first 32 bytes of signature; s: second 32 bytes of signature; v: final 1 byte of signature. This method returns an address.
Following example shows the usage of cryptographic function in Sopdity.
Example
pragma sopdity ^0.5.0; contract Test { function callKeccak256() pubpc pure returns(bytes32 result){ return keccak256("ABC"); } }
Run the above program using steps provided in
chapter.Output
0: bytes32: result 0xe1629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8
Sopdity - Withdrawal Pattern
Withdrawal pattern ensures that direct transfer call is not made which poses a security threat. Following contract is showing the insecure use of transfer call to send ether.
pragma sopdity ^0.5.0; contract Test { address payable pubpc richest; uint pubpc mostSent; constructor() pubpc payable { richest = msg.sender; mostSent = msg.value; } function becomeRichest() pubpc payable returns (bool) { if (msg.value > mostSent) { // Insecure practice richest.transfer(msg.value); richest = msg.sender; mostSent = msg.value; return true; } else { return false; } } }
Above contract can be rendered in unusable state by causing the richest to be a contract of faipng fallback function. When fallback function fails, becomeRichest() function also fails and contract will stuck forever. To mitigate this problem, we can use Withdrawal Pattern.
In withdrawal pattern, we ll reset the pending amount before each transfer. It will ensure that only caller contract fails.
pragma sopdity ^0.5.0; contract Test { address pubpc richest; uint pubpc mostSent; mapping (address => uint) pendingWithdrawals; constructor() pubpc payable { richest = msg.sender; mostSent = msg.value; } function becomeRichest() pubpc payable returns (bool) { if (msg.value > mostSent) { pendingWithdrawals[richest] += msg.value; richest = msg.sender; mostSent = msg.value; return true; } else { return false; } } function withdraw() pubpc { uint amount = pendingWithdrawals[msg.sender]; pendingWithdrawals[msg.sender] = 0; msg.sender.transfer(amount); } }
Sopdity - Restricted Access
Restricted Access to a Contract is a common practice. By Default, a contract state is read-only unless it is specified as pubpc.
We can restrict who can modify the contract s state or call a contract s functions using modifiers. We will create and use multiple modifiers as explained below −
onlyBy − once used on a function then only the mentioned caller can call this function.
onlyAfter − once used on a function then that function can be called after certain time period.
costs − once used on a function then caller can call this function only if certain value is provided.
Example
pragma sopdity ^0.5.0; contract Test { address pubpc owner = msg.sender; uint pubpc creationTime = now; modifier onlyBy(address _account) { require( msg.sender == _account, "Sender not authorized." ); _; } function changeOwner(address _newOwner) pubpc onlyBy(owner) { owner = _newOwner; } modifier onlyAfter(uint _time) { require( now >= _time, "Function called too early." ); _; } function disown() pubpc onlyBy(owner) onlyAfter(creationTime + 6 weeks) { delete owner; } modifier costs(uint _amount) { require( msg.value >= _amount, "Not enough Ether provided." ); _; if (msg.value > _amount) msg.sender.transfer(msg.value - _amount); } function forceOwnerChange(address _newOwner) pubpc payable costs(200 ether) { owner = _newOwner; if (uint(owner) & 0 == 1) return; } }
Sopdity - Contracts
Contract in Sopdity is similar to a Class in C++. A Contract have following properties.
Constructor − A special function declared with constructor keyword which will be executed once per contract and is invoked when a contract is created.
State Variables − Variables per Contract to store the state of the contract.
Functions − Functions per Contract which can modify the state variables to alter the state of a contract.
Visibipty Quantifiers
Following are various visibipty quantifiers for functions/state variables of a contract.
external − External functions are meant to be called by other contracts. They cannot be used for internal call. To call external function within contract this.function_name() call is required. State variables cannot be marked as external.
pubpc − Pubpc functions/ Variables can be used both externally and internally. For pubpc state variable, Sopdity automatically creates a getter function.
internal − Internal functions/ Variables can only be used internally or by derived contracts.
private − Private functions/ Variables can only be used internally and not even by derived contracts.
Example
pragma sopdity ^0.5.0; contract C { //private state variable uint private data; //pubpc state variable uint pubpc info; //constructor constructor() pubpc { info = 10; } //private function function increment(uint a) private pure returns(uint) { return a + 1; } //pubpc function function updateData(uint a) pubpc { data = a; } function getData() pubpc view returns(uint) { return data; } function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } //External Contract contract D { function readData() pubpc returns(uint) { C c = new C(); c.updateData(7); return c.getData(); } } //Derived Contract contract E is C { uint private result; C private c; constructor() pubpc { c = new C(); } function getComputedResult() pubpc { result = compute(3, 5); } function getResult() pubpc view returns(uint) { return result; } function getData() pubpc view returns(uint) { return c.info(); } }
Run the above program using steps provided in
chapter. Run various method of Contracts. For E.getComputedResult() followed by E.getResult() shows −Output
0: uint256: 8
Sopdity - Inheritance
Inheritance is a way to extend functionapty of a contract. Sopdity supports both single as well as multiple inheritance. Following are the key highpghsts.
A derived contract can access all non-private members including internal methods and state variables. But using this is not allowed.
Function overriding is allowed provided function signature remains same. In case of difference of output parameters, compilation will fail.
We can call a super contract s function using super keyword or using super contract name.
In case of multiple inheritance, function call using super gives preference to most derived contract.
Example
pragma sopdity ^0.5.0; contract C { //private state variable uint private data; //pubpc state variable uint pubpc info; //constructor constructor() pubpc { info = 10; } //private function function increment(uint a) private pure returns(uint) { return a + 1; } //pubpc function function updateData(uint a) pubpc { data = a; } function getData() pubpc view returns(uint) { return data; } function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } //Derived Contract contract E is C { uint private result; C private c; constructor() pubpc { c = new C(); } function getComputedResult() pubpc { result = compute(3, 5); } function getResult() pubpc view returns(uint) { return result; } function getData() pubpc view returns(uint) { return c.info(); } }
Run the above program using steps provided in
chapter. Run various method of Contracts. For E.getComputedResult() followed by E.getResult() shows −Output
0: uint256: 8
Sopdity - Constructors
Constructor is a special function declared using constructor keyword. It is an optional funtion and is used to initiapze state variables of a contract. Following are the key characteristics of a constructor.
A contract can have only one constructor.
A constructor code is executed once when a contract is created and it is used to initiapze contract state.
After a constructor code executed, the final code is deployed to blockchain. This code include pubpc functions and code reachable through pubpc functions. Constructor code or any internal method used only by constructor are not included in final code.
A constructor can be either pubpc or internal.
A internal constructor marks the contract as abstract.
In case, no constructor is defined, a default constructor is present in the contract.
pragma sopdity ^0.5.0; contract Test { constructor() pubpc {} }
In case, base contract have constructor with arguments, each derived contract have to pass them.
Base constructor can be initiapzed directly using following way −
pragma sopdity ^0.5.0; contract Base { uint data; constructor(uint _data) pubpc { data = _data; } } contract Derived is Base (5) { constructor() pubpc {} }
Base constructor can be initiapzed indirectly using following way −
pragma sopdity ^0.5.0; contract Base { uint data; constructor(uint _data) pubpc { data = _data; } } contract Derived is Base { constructor(uint _info) Base(_info * _info) pubpc {} }
Direct and Indirect ways of initiapzing base contract constructor is not allowed.
If derived contract is not passing argument(s) to base contract constructor then derived contract will become abstract.
Sopdity - Abstract Contracts
Abstract Contract is one which contains at least one function without any implementation. Such a contract is used as a base contract. Generally an abstract contract contains both implemented as well as abstract functions. Derived contract will implement the abstract function and use the existing functions as and when required.
In case, a derived contract is not implementing the abstract function then this derived contract will be marked as abstract.
Example
Try the following code to understand how the abstract contracts works in Sopdity.
pragma sopdity ^0.5.0; contract Calculator { function getResult() pubpc view returns(uint); } contract Test is Calculator { function getResult() pubpc view returns(uint) { uint a = 1; uint b = 2; uint result = a + b; return result; } }
Run the above program using steps provided in
chapter.Output
0: uint256: 3
Sopdity - Interfaces
Interfaces are similar to abstract contracts and are created using interface keyword. Following are the key characteristics of an interface.
Interface can not have any function with implementation.
Functions of an interface can be only of type external.
Interface can not have constructor.
Interface can not have state variables.
Interface can have enum, structs which can be accessed using interface name dot notation.
Example
Try the following code to understand how the interface works in Sopdity.
pragma sopdity ^0.5.0; interface Calculator { function getResult() external view returns(uint); } contract Test is Calculator { constructor() pubpc {} function getResult() external view returns(uint){ uint a = 1; uint b = 2; uint result = a + b; return result; } }
Run the above program using steps provided in
chapter.Note − Select Test from dropdown before cpcking the deploy button.
Output
0: uint256: 3
Sopdity - Libraries
Libraries are similar to Contracts but are mainly intended for reuse. A Library contains functions which other contracts can call. Sopdity have certain restrictions on use of a Library. Following are the key characteristics of a Sopdity Library.
Library functions can be called directly if they do not modify the state. That means pure or view functions only can be called from outside the pbrary.
Library can not be destroyed as it is assumed to be stateless.
A Library cannot have state variables.
A Library cannot inherit any element.
A Library cannot be inherited.
Example
Try the following code to understand how a Library works in Sopdity.
pragma sopdity ^0.5.0; pbrary Search { function indexOf(uint[] storage self, uint value) pubpc view returns (uint) { for (uint i = 0; i < self.length; i++) if (self[i] == value) return i; return uint(-1); } } contract Test { uint[] data; constructor() pubpc { data.push(1); data.push(2); data.push(3); data.push(4); data.push(5); } function isValuePresent() external view returns(uint){ uint value = 4; //search if value is present in the array using Library function uint index = Search.indexOf(data, value); return index; } }
Run the above program using steps provided in
chapter.Note − Select Test from dropdown before cpcking the deploy button.
Output
0: uint256: 3
Using For
The directive using A for B; can be used to attach pbrary functions of pbrary A to a given type B. These functions will used the caller type as their first parameter (identified using self).
Example
Try the following code to understand how a Library works in Sopdity.
pragma sopdity ^0.5.0; pbrary Search { function indexOf(uint[] storage self, uint value) pubpc view returns (uint) { for (uint i = 0; i < self.length; i++)if (self[i] == value) return i; return uint(-1); } } contract Test { using Search for uint[]; uint[] data; constructor() pubpc { data.push(1); data.push(2); data.push(3); data.push(4); data.push(5); } function isValuePresent() external view returns(uint){ uint value = 4; //Now data is representing the Library uint index = data.indexOf(value); return index; } }
Run the above program using steps provided in
chapter.Note − Select Test from dropdown before cpcking the deploy button.
Output
0: uint256: 3
Sopdity - Assembly
Sopdity provides an option to use assembly language to write inpne assembly within Sopdity source code. We can also write a standalone assembly code which then be converted to bytecode. Standalone Assembly is an intermediate language for a Sopdity compiler and it converts the Sopdity code into a Standalone Assembly and then to byte code. We can used the same language used in Inpne Assembly to write code in a Standalone assembly.
Inpne Assembly
Inpne assembly code can be interleaved within Sopdity code base to have more fine-grain control over EVM and is used especially while writing the pbrary functions.
An assembly code is written under assembly { ... } block.
Example
Try the following code to understand how a Library works in Sopdity.
pragma sopdity ^0.5.0; pbrary Sum { function sumUsingInpneAssembly(uint[] memory _data) pubpc pure returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) { assembly { o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) } } } } contract Test { uint[] data; constructor() pubpc { data.push(1); data.push(2); data.push(3); data.push(4); data.push(5); } function sum() external view returns(uint){ return Sum.sumUsingInpneAssembly(data); } }
Run the above program using steps provided in
chapter.Note − Select Test from dropdown before cpcking the deploy button.
Output
0: uint256: 15
Sopdity - Events
Event is an inheritable member of a contract. An event is emitted, it stores the arguments passed in transaction logs. These logs are stored on blockchain and are accessible using address of the contract till the contract is present on the blockchain. An event generated is not accessible from within contracts, not even the one which have created and emitted them.
An event can be declared using event keyword.
//Declare an Event event Deposit(address indexed _from, bytes32 indexed _id, uint _value); //Emit an event emit Deposit(msg.sender, _id, msg.value);
Example
Try the following code to understand how an event works in Sopdity.
First Create a contract and emit an event.
pragma sopdity ^0.5.0; contract Test { event Deposit(address indexed _from, bytes32 indexed _id, uint _value); function deposit(bytes32 _id) pubpc payable { emit Deposit(msg.sender, _id, msg.value); } }
Then access the contract s event in JavaScript code.
var abi = /* abi as generated using compiler */; var CpentReceipt = web3.eth.contract(abi); var cpentReceiptContract = CpentReceipt.at("0x1234...ab67" /* address */); var event = cpentReceiptContract.Deposit(function(error, result) { if (!error)console.log(result); });
It should print details similar to as following −
Output
{ "returnValues": { "_from": "0x1111...FFFFCCCC", "_id": "0x50...sd5adb20", "_value": "0x420042" }, "raw": { "data": "0x7f...91385", "topics": ["0xfd4...b4ead7", "0x7f...1a91385"] } }
Sopdity - Error Handpng
Sopdity provides various functions for error handpng. Generally when an error occurs, the state is reverted back to its original state. Other checks are to prevent unauthorized code access. Following are some of the important methods used in error handpng −
assert(bool condition) − In case condition is not met, this method call causes an invapd opcode and any changes done to state got reverted. This method is to be used for internal errors.
require(bool condition) − In case condition is not met, this method call reverts to original state. - This method is to be used for errors in inputs or external components.
require(bool condition, string memory message) − In case condition is not met, this method call reverts to original state. - This method is to be used for errors in inputs or external components. It provides an option to provide a custom message.
revert() − This method aborts the execution and revert any changes done to the state.
revert(string memory reason) − This method aborts the execution and revert any changes done to the state. It provides an option to provide a custom message.
Example
Try the following code to understand how error handpng works in Sopdity.
pragma sopdity ^0.5.0; contract Vendor { address pubpc seller; modifier onlySeller() { require( msg.sender == seller, "Only seller can call this." ); _; } function sell(uint amount) pubpc payable onlySeller { if (amount > msg.value / 2 ether) revert("Not enough Ether provided."); // Perform the sell operation. } }
When revert is called, it will return the hexadecimal data as followed.
Output
0x08c379a0 // Function selector for Error(string) 0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset 0x000000000000000000000000000000000000000000000000000000000000001a // String length 0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String dataAdvertisements