Solidity Tutorial
Solidity Tutorial
Audience
This tutorial targets novice developers and those new to Solidity. It guides them in
understanding basic through more advanced concepts in Solidity. After completing
this tutorial, your firm foundation in Solidity and level of expertise will allow you to
begin developing and easily build on your knowledge.
Prerequisites
The tutorial assumes your familiarity with blockchain, and general programming.
Solidity - Overview
Solidity is a contract-oriented, high-level programming language for implementing
smart contracts. Solidity is highly influenced by C++, Python and JavaScript and
has been designed to target the Ethereum Virtual Machine (EVM).
Solidity is statically typed, supports inheritance, libraries and complex user-defined
types programming language.
You can use Solidity to create contracts for uses such as voting, crowdfunding,
blind auctions, and multi-signature wallets.
What is Ethereum?
Ethereum is a decentralized ie. blockchain platform that runs smart contracts i.e.
applications that run exactly as programmed without any possibility of downtime,
censorship, fraud or third-party interference.
Basic Syntax
A Solidity source files can contain an any number of contract definitions, import
directives and pragma directives.
Let's start with a simple source file of Solidity. Following is an example of a Solidity
file −
pragma solidity >=0.4.0 <0.6.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
Pragma
The first line is a pragma directive which tells that the source code is written for
Solidity version 0.4.0 or anything newer that does not break functionality 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 earlier 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 solidity ^0.4.0;
Contract
A Solidity contract is a collection of code (its functions) and data (its state) that
resides at a specific address on the Ethereumblockchain.
The line 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 Solidity 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 Solidity –
First Application
We're using Remix IDE to Compile and Run our Solidity Code base.
Step 1 − Copy the given code in Remix IDE Code Section.
Example
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(uint){
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
}
Output
0: uint256: 3
Comments
Solidity supports both C-style and C++-style comments, Thus −
Any text between a // and the end of a line is treated as a comment and is
ignored by Solidity Compiler.
Any text between the characters /* and */ is treated as a comment. This may
span multiple lines.
Example
The following example shows how to use comments in Solidity.
function getResult() public view returns(uint){
// This is a comment. It is similar to comments in C++
/*
* This is a multi-line comment in solidity
* It is very similar to comments in C Programming
*/
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
Variable - 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 like to store information of various data types like 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
Solidity offers the programmer a rich assortment of built-in as well as user defined
data types. Following table lists down seven basic C++ data types –
Integer int8 to int256 Signed int from 8 bits to 256 bits. int256 is
same as int.
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);
Variables
Solidity 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.
Solidity 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 solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
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 solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
storedData = 10;
}
function getResult() public view returns(uint){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return result; //access the local variable
}
}
Example
pragma solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
storedData = 10;
}
function getResult() public 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 Solidity First Application 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 Hash of the given block - only works for
(bytes32) 256 most recent, excluding current,
blocks
Variable Scope
Scope of local variables is limited to function in which they are defined but State
variables can have three types of scopes.
Public − Public state variables can be accessed internally as well as via
messages. For a public 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 solidity ^0.5.0;
contract C {
uint public data = 30;
uint internal iData= 10;
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. Solidity 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
Solidity supports the following arithmetic operators −
Assume variable A holds 10 and variable B holds 20, then –
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 * (Multiplication)
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 division
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
Example
The following code shows how to use arithmetic operators in Solidity.
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(uint){
uint a = 1;
uint b = 2;
uint result = a + b; //arithmetic operation
return result;
}
}
Run the above program using steps provided in Solidity First Application chapter.
Output
0: uint256: 3
Comparison Operators
Solidity supports the following comparison operators −
Assume variable A holds 10 and variable B holds 20, then −
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.
Logical Operators
Solidity supports the following logical operators −
Assume variable A holds 10 and variable B holds 20, then –
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
Solidity supports the following bitwise operators −
Assume variable A holds 2 and variable B holds 3, then −
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 like the >> operator, except that the bits shifted in on the
left are always zero.
Ex: (A >>> 1) is 1.
Assignment Operators
Solidity supports the following assignment operators −
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 multiplies 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 divides 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 applies to Bitwise operators so they will become like <<=, >>=,
>>=, &=, |= 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.
1
? : (Conditional )
If Condition is true? Then value X : Otherwise value Y
Example
pragma solidity ^0.5.0;
contract SolidityTest {
uint storedData;
constructor() public{
storedData = 10;
}
function getResult() public view returns(string memory){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return integerToString(result);
}
function integerToString(uint _i) internal pure
returns (string memory _uintAsString) {
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 Solidity First Application chapter.
Output
0: string: 3
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 lines.
Solidity supports all the necessary loops to ease down the pressure of
programming.
1
While Loop
The most basic loop in Solidity is the while loop which would be discussed in
this chapter.
2
do...while Loop
The do...while loop is similar to the while loop except that the condition check
happens at the end of the loop.
3
For Loop
The for loop is the most compact form of looping. It includes the following three
important parts.
4
Loop Control
Solidity provides full control to handle loops and switch statements.
While Loop
The most basic loop in Solidity is the while loop which would be discussed in this
chapter. The purpose of a while loop is to execute a statement or code block
repeatedly as long as an expression is true. Once the expression
becomes false, the loop terminates.
Flow Chart
The flow chart of while loop looks as follows −
Syntax
The syntax of while loop in Solidity is as follows −
while (expression) {
Statement(s) to be executed if expression is true
}
do...while loop
The do...while loop is similar to the while loop except that the condition check
happens at the end of the loop. This means that the loop will always be executed at
least once, even if the condition is false.
Flow Chart
The flow chart of a do-while loop would be as follows −
Syntax
The syntax for do-while loop in Solidity is as follows −
do {
Statement(s) to be executed;
} while (expression);
Note − Don't miss the semicolon used at the end of the do...while loop.
For Loop
The for loop is the most compact form of looping. It includes the following three
important parts −
The loop initialization where we initialize our counter to a starting value. The
initialization statement is executed before the loop begins.
The test statement which will test if a given condition is true or not. If the
condition is true, then the code given inside the loop will be executed,
otherwise the control will come out of the loop.
The iteration statement where you can increase or decrease your counter.
You can put all the three parts in a single line separated by semicolons.
Flow Chart
The flow chart of a for loop in Solidity would be as follows −
Syntax
The syntax of for loop is Solidity is as follows −
for (initialization; test condition; iteration statement) {
Statement(s) to be executed if test condition is true
}
Loop Control
Solidity provides full control to handle loops and switch statements. There may be a
situation when you need to come out of a loop without reaching its bottom. There
may also be a situation when you want to skip a part of your code block and start
the next iteration of the loop.
To handle all such situations, Solidity provides break and continue statements.
These statements are used to immediately come out of any loop or to start the next
iteration of any loop respectively.
1
if statement
The if statement is the fundamental control statement that allows Solidity to
make decisions and execute statements conditionally.
2
if...else statement
The 'if...else' statement is the next form of control statement that allows Solidity
to execute statements in a more controlled way.
3
if...else if... statement.
The if...else if... statement is an advanced form of if...else that allows Solidity to
make a correct decision out of several conditions
The if statement is the fundamental control statement that allows Solidity to make
decisions and execute statements conditionally.
Syntax
The syntax for a basic if statement is as follows −
if (expression) {
Statement(s) to be executed if expression is true
}
Here a Solidity expression is evaluated. If the resulting value is true, the given
statement(s) are executed. If the expression is false, then no statement would be
not executed. Most of the times, you will use comparison operators while making
decisions.
Syntax
if (expression) {
Statement(s) to be executed if expression is true
} else {
Statement(s) to be executed if expression is false
}
Here Solidity expression is evaluated. If the resulting value is true, the given
statement(s) in the 'if' block, are executed. If the expression is false, then the given
statement(s) in the else block are executed
Syntax
The syntax of an if-else-if statement is as follows −
if (expression 1) {
Statement(s) to be executed if expression 1 is true
} else if (expression 2) {
Statement(s) to be executed if expression 2 is true
} else if (expression 3) {
Statement(s) to be executed if expression 3 is true
} else {
Statement(s) to be executed if no expression is true
}
There is nothing special about this code. It is just a series of if statements, where
each if is a part of the else clause of the previous statement. Statement(s) are
executed based on the true condition, if none of the conditions is true, then
the else block is executed.
Strings
Solidity supports String literal using both double quote (") and single quote ('). It
provides string as a data type to declare a variable of type String.
pragma solidity ^0.5.0;
contract SolidityTest {
string data = "test";
}
In above example, "test" is a string literal 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. Solidity provides inbuilt conversion
between bytes to string and vice versa. In Solidity we can assign String literal to a
byte32 type variable easily. Solidity considers it as a byte32 literal.
pragma solidity ^0.5.0;
contract SolidityTest {
bytes32 data = "test";
}
Escape Characters
Sr.No. Character & Description
1
\n
Starts a new line.
2
\\
Backslash
3
\'
Single Quote
4
\"
Double Quote
5
\b
Backspace
6
\f
Form Feed
7
\r
Carriage Return
8
\t
Tab
9
\v
Vertical Tab
10
\xNN
Represents Hex value and inserts appropriate bytes.
11
\uNNNN
Represents Unicode value and inserts UTF-8 sequence.
Declaring Arrays
To declare an array of fixed size in Solidity, 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 valid Solidity 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 Solidity, the programmer specifies the type of
the elements as follows −
type[] arrayName;
Initializing Arrays
You can initialize Solidity 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 initialization 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 3 rd 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 3 rd 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 Solidity.
pragma solidity ^0.5.0;
contract test {
function testArray() public pure{
uint len = 7;
//dynamic array
uint[] memory a = new uint[](7);
assert(a.length == 7);
assert(b.length == len);
//static array
uint[3] memory c = [uint(1) , 2, 3];
assert(c.length == 3);
}
}
Enums
Enums restrict a variable to have one of only a few predefined values. The values in
this enumerated list 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 application 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 Solidity.
pragma solidity ^0.5.0;
contract test {
enum FreshJuiceSize{ SMALL, MEDIUM, LARGE }
FreshJuiceSize choice;
FreshJuiceSize constant defaultChoice = FreshJuiceSize.MEDIUM;
Run the above program using steps provided in Solidity First Application chapter.
First Click setLarge Button to set the value as LARGE then click getChoice to get
the selected choice.
Output
uint8: 2
Click getDefaultChoice Button to get the default choice.
Output
uint256: 1
Structs
Struct types are used to represent a record. Suppose you want to keep track of your
books in a library. 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;
}
contract test {
struct Book {
string title;
string author;
uint book_id;
}
Book book;
Run the above program using steps provided in Solidity First Application chapter.
First Click setBook Button to set the value as LARGE then click getBookId to get
the selected book id.
Output
uint256: 1
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 public. Solidity automatically create getter for it.
Example
Try the following code to understand how the mapping type works in Solidity.
pragma solidity ^0.5.0;
contract LedgerBalance {
mapping(address => uint) public balances;
Conversions
Solidity allows implicit as well as explicit conversion. Solidity compiler allows implicit
conversion between two data types provided no implicit 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.
Explicit Conversion
We can explicitly 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 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
Ether Units
In solidity we can use wei, finney, szabo or ether as a suffix to a literal 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, Solidity 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);
Special Variables
Special variables are globally available variables and provides information about the
blockchain. Following is the list of special variables −
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.gaslimit (uint)
Current block gaslimit.
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 (alias 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 Solidity.
pragma solidity ^0.5.0;
contract LedgerBalance {
mapping(address => uint) public balances;
Run the above program using steps provided in Solidity First Application chapter.
First Click updateBalance Button to set the value as 10 then look into the logs
which will show the decoded output as −
Output
{
"0": "uint256: 10"
}
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
Solidity.
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 lines between two contract definitions.
pragma solidity ^0.5.0;
contract LedgerBalance {
//...
}
contract Updater {
//...
}
One Blank Line Rule − Use 1 Blank line between two functions. In case of
only declaration, no need to have blank lines.
pragma solidity ^0.5.0;
contract A {
function balance() public pure;
function account() public pure;
}
contract B is A {
function balance() public pure {
// ...
}
function account() public pure {
// ...
}
}
Maximum Line Length − A single line should not cross 79 characters so that
readers can easily parse the code.
Wrapping rules − First argument be in new line 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 publicKey,
uint256 amount,
bytes32[] options
);
MultipleArguments(
sender,
recipient,
publicKey,
amount,
options
);
contract A {
constructor() public {
// ...
}
function() external {
// ...
}
// External functions
// ...
// Public functions
// ...
// Internal functions
// ...
// Private functions
// ...
}
Avoid extra whitespaces − Avoid whitespaces immediately inside
parenthesis, brackets or braces.
Control structures − Braces should open on same line as declaration. Close
on their own line maintaining the same indentation. Use a space with
opening brace.
pragma solidity ^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
visibility label. Visibility label should come first before any custom modifier.
function kill() public onlyowner {
selfdestruct(owner);
}
Order of Layout
Elements should be layout in following order.
Pragma statements
Import statements
Interfaces
Libraries
Contracts
Within Interfaces, libraries 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/libraries in a file, use name of core
contract/library.
Owned.sol
pragma solidity ^0.5.0;
// Owned.sol
contract Owned {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
//....
}
function transferOwnership(address newOwner) public onlyOwner
{
//...
}
}
Congress.sol
pragma solidity ^0.5.0;
// Congress.sol
import "./Owned.sol";
Struct Names
− Use CapWords Style like SmartCoin.
Event Names
Function Names
Constants
− Use all capital letters with underscore to seperate words like MAX_BLOCKS.
Modifier Names
Enum Names