Blockchain is the backbone of cryptocurrency which redefines the way we communicate over the internet. It creates a decentralized, token-based system where contributors become the owner of the asset rather than guests.
Smart Contracts play a vital role in Blockchain popularity as it makes transactions safer and organized.
Ethereum is an open-source platform that allows anyone to build and run dapps on a blockchain. It allows users to create Smart Contracts, which can be deployed and executed by the Ethereum Virtual Machine (EVM). Solidity is the language used for creating these smart contracts.
In this article, we will learn to create a smart contract using Solidity.
Getting Started
Let's begin with basic terminologies.
Blockchain
A blockchain is an auditable and irreversible database where data can only be added. In a blockchain, the data can be added as blocks in which each block has the address of the previous one, hence called the blockchain.
Crypto Currency
Cryptocurrency is a digital currency in which all transactions use cryptography to add the block to a blockchain on a decentralized system. A blockchain is a collection of nodes responsible for validating the cryptocurrency. Though Bitcoin is the most popular cryptocurrency, Ethereum (ether) can also be used for blockchain transactions.
Ethereum
Ethereum is an open-source decentralized platform built on blockchain and is used to run our smart contracts. It is not only a cryptocurrency but also a sophisticated application that executes the smart contracts on the blockchain so as to avoid the chances of any fraud attempts in the transactions. We use Ethereum Virtual Machine (EVM) as the runtime for running the smart contracts.
Smart Contracts
Smart contracts are program snippets compiled and executed by the EVM and stored on a blockchain. It is executed automatically when the predefined conditions are met. It helps you to do safe transactions without the involvement of a third party. The good part of smart contract-based transactions is that these transactions are irreversible but traceable.
Solidity is the most widely used programming language to create and write smart contracts even though there are other languages such as Mutan, Serpent and LLL available in the market.
Ethereum Virtual Machine (EVM)
The Ethereum Virtual Machine is a computing engine used for running smart contracts. It acts as a software platform for building and deploying decentralized apps.
Let's have a look into the working of an EVM.
The smart contract (Solidity code) is compiled by the Ethereum compiler and creates an EVM bytecode. These bytecodes are the intermediate codes executed by the EVM. It creates different blocks after bytecode execution. Finally, the deployed contracts are mapped to the respective blocks.
We can find multiple standalone implementations of EVM such as
- Py-EVM - Python
- evmone - C++
- ethereumjs-vm - JavaScript
- eEVM - C++
- Hyperledger Burrow - Go
Solidity
Solidity is the commonly used high-level object-oriented language for implementing smart contracts. It is a curly-bracket based and ECMAScript-like syntax language having almost similar syntax to C++, JavaScript and Python. It is statically typed and supports complex member variables for contracts. With Solidity, you can create contracts for applications such as voting, crowdfunding, and multi-signature wallets.
Setup the environment
You can execute a Smart contract in two ways
- Offline mode
- Online mode
Offline mode
Let's start with the software requirements.
- Node.js - An open-source JavaScript runtime environment used to execute JavaScript code outside a web browser.
- Truffle - The most popular development framework for Ethereum.
Ganache - Provides a local network that shows different test / real blockchain accounts and transactions on the IDE/console. It is a part of the Truffle suite.
Install Truffle globally.
npm install -g truffle
- Download and install ganache-cli.
Online mode
Remix Ethereum IDE is an online platform used to create smart contracts using Solidity with zero setup time. It has an offline installer to run it locally. Check the offline installer here Remix desktop
Now that all the tools are installed, let us explore some of the fundamental concepts of Solidity.
Solidity fundamentals
Version Pragma
Pragma directive specifies the compiler version for running the source code. All solidity programs should begin with a pragma . Note that this statement is local to the solidity program, which means you have to specify this line for all solidity programs.
pragma solidity >=0.7.0 <0.9.0;
Contract
This keyword is used to create a smart contract. By convention, the name of the contract is usually the name of the solidity file. Every function and variable declaration in the file will be encapsulated within the smart contract.
contract Test{
// Functions and Data
}
Variables
Variables are reserved memory locations to store value. You may like to store information on various data types like character, wide character, integer, floating point, double floating point, boolean etc.
Solidity types
Solidity is a statically typed language, hence we have to specify the type of each variable on their declaration. Like other languages, Solidity has value types and reference types.
Value types - Value type variables store their own data. These are the basic data types provided by solidity. Value type data in the solidity are listed below:
- Boolean: This data type is used to store True or False values.
- Integer: This data type is used to store whole numbers. We can use int and uint to declare signed and unsigned integers respectively.
- Fixed Point Numbers: This data type is used to store floating point numbers. We can use fixed and unfixed to declare signed and unsigned fixed-point numbers respectively.
- Address: Address holds a 20-byte value which represents the size of an Ethereum address. An address can be used to get the balance of a blockchain account or to transfer the balance using the getbalance() or settransfer() method respectively.
- Bytes and Strings: Bytes are used to store a fixed-sized character set while the string is used to store the character set equal to or more than a byte.
- Enums: It is used to create user-defined data types, and also to assign a name to an integer constant which makes the contract more readable and maintainable.
// Solidity program to demonstrate value types
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
// Creating a contract
contract Types {
// Initializing Bool variable
bool public boolean = false;
// Initializing Integer variable
int32 public int_var = -12345;
// Initializing String variable
string public str = "Codemaker";
// Initializing Byte variable
bytes1 public b = "v";
// Defining an enumerator
enum week { sunday, monday, tuesday, wednesday, thursday, friday, saturday }
}
Reference Types - Reference type variables store the location of the data. They don't share the data directly. The reference types in solidity are listed below:
- Arrays: An array is a collection of similar data with a name and each element is identified with the help of an index.
- Struct: The structure is a group of different data types. It helps the user to create and define their own data type.
- Mapping: Mapping is the most used reference type which stores the data in a key-value pair where a key can be any value type.
// Solidity program to demonstrate Reference Types
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
// Creating a contract
contract Types {
// Defining an array
uint[5] public array = [uint(1), 2, 3, 4, 5] ;
// Defining a Structure
struct student {
string name;
string subject;
uint8 marks;
}
// Creating a structure object
student public std1;
// Creating a mapping
mapping (address => student) result;
address[] student_result;
}
Function
A function is a group of reusable codes that can be used anywhere in your application. We can define a function using the function keyword, a unique function name, a list of parameters, and a block of statements surrounded by curly braces. It can be specified as private, internal, external or public (default).
- Private: Functions and state variables are only visible for the contract which are defined.
- Public: Functions and state variables can be accessed anywhere in the program.
- Internal: Similar to private but Functions and state variables can only be accessed within the contracts derived from the defined contracts.
- View: These are read-only functions which guarantee the state of the variable. Syntax
function function-name(parameter-list) scope returns() {
//statements
}
Example
// Solidity program to demonstrate Functions
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract MathOperations {
function addNumbers() public pure returns(uint){
uint a = 100; // local variable
uint b = 200;
uint result = a + b;
return result;
}
}
Modifiers
Modifier allows the control of the behavior of a function. They can be used in a variety of scenarios. For instance, checking who has access to a function before executing that function.
// Solidity program to demonstrate Modifiers
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract ModifierTest {
address testAddress;
constructor() {
testAddress = msg.sender;
}
// Check if the function is called by the owner of the contract
modifier onlyOwner() {
if (msg.sender == testAddress) {
_;
}
}
// Can only be called by the owner - using onlyOwner modifier
function test() public onlyOwner {
}
}
If the condition of the modifier is met while calling the function, the function body is inserted where the special symbol "_;"
appears in the modifier definition. Then the code is executed else an exception is thrown.
Constructors
Constructor is an optional function which is automatically executed at the time of contract creation. We can define a constructor using the constructor keyword. It can be public or internal. The contract will create a default constructor if there is no constructor specified.
contructor() public {}
contract ConstructorTest {
uint regNo;
constructor() public {
regNo = 10;
}
}
Events
An event stores arguments passed in the transaction logs. It is helpful to get the current state of the contract while calling the function. It can be used to notify the application regarding the changes made in the contracts.
Syntax
event Transfer(address indexed from, address indexed to, uint _value);
Example
emit Transfer(msg.sender, receiverAddress, msg.value);
Error handling
Solidity provides various functions for error handling. However, the state of the blockchain is reverted back to its original state when an error occurs. Also, there is an option to prevent unauthorized code access. Following are some of the important methods used in error handling.
assert(bool condition) − In case the condition is not met, the method call causes an invalid opcode and any changes made to the state will get reverted. This can be used for internal errors.
require(bool condition) − In case the condition is not met, the method call reverts to the original state. This can be used for external components.
require(bool condition, string memory message) − The method is to be used for errors in inputs or external components. It has an option for a custom message.
revert() − The method aborts the execution and reverts any changes done to the state.
revert(string memory reason) − It has an option for a custom message.
// Solidity program to demonstrate Error handling
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract ErrorHandling {
address public seller;
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function sell(uint amount) public payable onlySeller {
if (amount > msg.value / 2 ether)
revert("Not enough Ether provided.");
// Perform the sell operation.
}
}
First Smart Contract
The fundamentals of Solidity are covered in the above sessions. Let's try to create and deploy our first smart contract.
Let's begin with the project folder creation. Subsequently, let's initialize the project with Truffle by the following command.
truffle init
truffle init
will create the necessary project files which include Migrations.sol
, 1_initial_migration.js
and truffle-config.js
. Likewise, it will create three folders - contracts, migrations and test. the contracts folder contains smart contracts, the migration folder contains codes for deployment and the test folder contains codes for testing the smart contracts.
The initial project structure will look like this,
Let's have a look at the project structure.
Contracts - Here you can create all your .sol smart contracts. The
Migrations.sol
is a smart contract created by Truffle to keep the migration history. Don't make any changes to theMigrations.sol
file.Migrations - It contains the files that help you to deploy your smart contracts.
The1_initial_migartion.js
file deploys theMigrations.sol
contract. You can also create migration files for your contracts. Truffle runs the migration in ascending order in terms of the prefix therefore developers are required to assign the prefixes in ascending order(Eg:2_name_file.js
).Test - Here you can create your test files. Truffle provides an automated testing framework to test your contracts using Solidity and Javascript.
Build - A build folder will be automatically created after the compilation and it contains low-level details of each of your contracts such as the ABI and bytecode. The information is useful when you refer to the contract outside the truffle environment. We can find the address of the deployed contracts in the build files.
Truffle Config - It contains project configurations such as network and compilers. You can set your network to either the Ganache local blockchain, a mainnet or a test network like Ropsten.
1. Write the contract
Now, we can create a HelloWorld.sol
smart contract. In this example, the constructor takes a string parameter and assigns it to a global variable name. The name can be changed using the function changeName(string)
which acts as a setter, while getName()
acts as a getter.
Create a file named 1_HelloWorld.sol and place it under the contracts folder then add the following code to it.
// Solidity program to demonstrate Hello World
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
// Creating a contract
contract HelloWorld {
string public name;
constructor(string memory yourName) public{
name = yourName;
}
function changeName(string memory yourName) public{
name = yourName;
}
function getName() public view returns(string memory){
return name;
}
}
2. Setup the migration
Create a new migration file with a prefix greater than 1 ( 2_hello_migartion.js
) inside the migration folder to deploy the HelloWorld.sol
contract.
Insert the following code snippet,
const HelloWorld = artifacts.require("HelloWorld");
module.exports = function (deployer) {
const yourName = "Codemaker";
deployer.deploy(HelloWorld, yourName);
};
The artifacts.require()
notifies the truffle which contract you want to interact with and deployer.deploy()
function refers to the parameter we need to pass to the constructor.
3. Compile and deploy
Compile your project using the following command
truffle compile
We can see a build folder inside the project folder if the compilation is successful. We have to use Turffle and Ganache to deploy and test the contracts.
Let's begin with Ganache. Open Ganache IDE, and select "QuickStart" from the window.
Next, go to truffle-config.js and modify the network details by uncommenting the development section.
Make sure the RPC server port from Ganache is mapped in the
networks.port
value.
Deploy the contract using the following command.
truffle deploy --network development
After successful deployment, you will get the contract details such as the contract address and the block information.
4. Test the contracts
Create a test filetest.js with .js prefix in the test folder and add the following code.
// to interact with the contract
const HelloWorld = artifacts.require("HelloWorld");
contract('HelloWorld', () => {
// initialise the contract instance before running tests
let contractInstance = null;
before(async () => {
contractInstance = await HelloWorld.deployed();
});
// TEST 1
it('initial name should be Codemaker', async () => {
// call contract's function
const currentName = await contractInstance.getName.call();
// check condition
assert.equal(currentName, "Codemaker", "the name is not Codemaker");
});
// TEST 2
it('should change name in Vishnu', async () => {
// change name in contract
await contractInstance.changeName("Vishnu");
// get the current name
const currentName = await contractInstance.getName.call();
// check condition
assert.equal(currentName, "Vishnu", "the name is not Vishnu");
});
});
Let's understand the code,
The before()
function executes in advance of the execution of the tests such that we can initialize the contract instance. The call()
function is used when the method does not modify the state variables of the contract. We used call() in the getName()
function else it would have returned the transaction receipt.
We have defined two test cases here. The first test verifies parameters in the contructor, gets the value using getter method and uses assert to check the equality. The second test tries to change the name using changeName()
.
Run the test using the following command
truffle test
There you have it! Your own smart contract deployed on the blockchain :)
5. Working with Remix IDE
Remix is an online IDE used to develop smart contracts using the Solidity language.
Let's try HelloWorld.sol
smart contract in the online Remix Ethereum IDE.
- Open Remix IDE on your browser.
- Select on the
New File
and choose theSolidity
environment.
- Now, you will get a code section. Write your contract logic in the code window and click the Compile button to compile it.
- Click on the Deploy button to execute the code.
- Click on the method calls under the deployed contracts to run the program.
- Click on the console to see the result.
- Click on the Debug button to debug the contract. It shows each function call and variable assignments.
Thanks for reading this article.
If you enjoyed this article, please click on the heart button ♥ and share to help others find it!
The full source code of this tutorial is available on https://github.com/codemaker2015/solidity-smart-contract-examples
Here are some useful links,
- https://docs.soliditylang.org/en/v0.8.11
- https://remix-project.org/
- https://github.com/ethereum/remix-desktop/releases
Originally posted on Medium -
Create and deploy your first smart contract with Solidity
Top comments (0)