A smart contract is a computer program which is intended to facilitate, verify, or enforce a negotiation/contract that was done in real life.
The Decentralized Applications (ĐApps) running on the Ethereum network are nothing more than a bunch of Complex Smart Contracts.
To start with Smart Contracts, you'll need the below mentioned tools.
Mist Browser is a DApp browser, built on top of Chromium Browser.
Download Latest Version of Mist from Github Releases Page.
Note: Mist has Ethereum Wallet built into it, so no need to download wallet seperately, just the Ethereum Mist would do.
sudo dpkg -i Mist-linux64-0-9-0.debMain Network or Test Network, select Test Network.Test Network, so that we don't have to spend any real money while learning.Rinkeby and Ropsten, we're going to use Rinkeby, because obtaining free Test Ether on Rinkeby is much easier.To create Smart Contracts, you're going to need some Ethereum on the Rinkeby test network, which can be obtained by following these steps:
Remix IDE is available as an Online IDE as well as it's bundled with the Mist Browser you downloaed.
Online Version: Remix IDE
Mist Remix IDE: Go to Develop -> Open Remix IDE.
Let's suppose there is a company which wants to pay it's employees equal share of the total earnings, using a Smart Contract.
pragma something; <--- Solidity Version information for compiler
contract ContractName{
constructor(){} <--- Initialization stuff goes here
fallback(){} <--- Called whenever someone sends Ether
someFunction1(){} <--- Normal function
someFunction2(){} <--- Normal function
}
There are a couple of types of functions which are required in a smart contract:
Constructor Function: The function which is called only once, when you deploy the smart contract. For example it can be used to receive the initial Ether sent to it, at the time of deployment.Fallback Function: The function without a name (literally no name, defined as function (){ code... }) which is invoked when someone sends Ether to the address of your smart contract. In the lack of this function, Ether sent to the smart contract will be rejected.There's also this thing called a Function Modifiers which are used to change the behaviour of a function, though they're not essential. For example, modifiers can check a condition prior to executing a function.
Copy Friendly Version: PayEmployees.sol
//The contract should start with the Solidity version it is written for.
pragma solidity ^0.4.0;
contract PayEmployees {
address[] employees = [0xdd870fa1b7c4700f2bd7f44238821c26f7392148, 0x583031d1113ad414f02576bd6afabfb302140225];
uint totalReceived = 0;
mapping(address => uint) withdrawnAmounts;
//Defining constructor as payable allows it to receive ethereum at the time of creation.
function PayEmployees() payable{
updateTotalReceived();
}
//fallback function, invoked ethereum is sent to the smart contract's address.
function () payable {
updateTotalReceived();
}
function updateTotalReceived() internal {
totalReceived += msg.value;
}
//Function modifiers are used to imply restrictions on the function calls.
modifier canWithdraw() {
bool contains = false;
for(uint i =0; i < employees.length; i++) {
if(employees[i] == msg.sender) {
contains = true;
break;
}
}
require(contains);
//This "_;" will be replaced by the actual function body
_;
}
//this function uses canWithdraw modifier to check whether the address belongs to one of the employees.
function withdraw() canWithdraw {
uint amountAllocated = totalReceived/employees.length;
uint amountWithdrawn = withdrawnAmounts[msg.sender];
uint amount = amountAllocated - amountWithdrawn;
withdrawnAmounts[msg.sender] = amountWithdrawn + amount;
if(amount > 0){
msg.sender.transfer(amount);
}
}
}
Let's take a look what it's all about.
pragma solidity ^0.4.0;
contract PayEmployees {
address[] employees = [0xdd870fa1b7c4700f2bd7f44238821c26f7392148, 0x583031d1113ad414f02576bd6afabfb302140225];
uint totalReceived = 0;
mapping(address => uint) withdrawnAmounts;
...
Pragma in general refers to an instruction which tells the compiler it how it should treat the code. In our smart contract the first line pragma solidity ^0.4.0; simply tells that the smart contract is written for Solidity version 0.4.0 or anything newer that does not break or alter the functionality (up to, but not including, version 0.5.0)
The next line creates a contract named PayEmployees. A contract is similar to a class, it's basically a collection of code containing variables and functions.
We need a list of the wallet addresses of all our employees, address[] employees creates an array in which we store the wallet addresses.
Constructor Function
...
function PayEmployees() payable{
updateTotalReceived();
}
...
This is the constructor, the function which is called only once, when we deploy the contract on the network. In our case, we're just updating the variable which stores the total ether received by our smart contract, to include the ether transferred to it at the time of deployment.
The payable keyword signifies that the function can receive money. Removing this keyword will make the smart contract reject the payment sent to it at the time of initialization.
Fallback Function
...
function () payable {
updateTotalReceived();
}
...
A fallback function is invoked whenever someone sends ether to the address of our contract's address. We've marked it as payable because who doesn't want money?
A Normal Function
...
function updateTotalReceived() internal {
totalReceived += msg.value;
}
...
Just because we wanted another function to update the totalReceived variable. We could've done without this function, but it would've meant writing two identical statements in the constructor and fallback function, programmers don't do that. (Yeah yeah, I know, we did the same thing by invoking the fuction twice, but it is supposed to be better.)
Also, msg is a variable containing all the details of the transaction, msg.value the number of wei (smallest unit of ether) sent, msg.sender is the address of the sender.
Modifiers
...
modifier canWithdraw() {
bool contains = false;
for(uint i =0; i < employees.length; i++) {
if(employees[i] == msg.sender) {
contains = true;
}
}
require(contains); //this should be true for the function to proceed to the next line.
_;
}
...
Modifiers are there to change the behaviour of functions. For example, modifiers can check a condition prior to executing a function. In a Function Modifier, solidity replaces the _; by the body of the function, which in this case will be the withdraw() function's body.
We're including a modifier in this smart contract just for the sake of familiarising ourselves with it, it's just checking one by one that the address which wants to invoke the withdraw() function is actually present in our array of employee addresses. The same could've been easily achieved by writing a similar check inside of our withdraw() function.
A better example would have been if we had 3 different kinds of withdraw() functions, each doing something differently, and each needed to check whether the address belongs to an employee, we won't have to write the same condition to verify that 3 times.
Withdrawing Ether
...
function withdraw() canWithdraw {
uint amountAllocated = totalReceived/employees.length;
uint amountWithdrawn = withdrawnAmounts[msg.sender];
uint amount = amountAllocated - amountWithdrawn;
withdrawnAmounts[msg.sender] = amountWithdrawn + amount;
if(amount > 0){
msg.sender.transfer(amount);
}
}
}
Just a simple withdraw function that does the following things:
Note: Every operation in a smart contract costs gas to execute, so you should minimize the number of operations in your smart contracts. We'll learn more about this in the coming tutorials.
We have coded our first smart contract, the employees will be so pissed if we don't deploy it on the network.
employees array in the code.Mist -> Contracts -> Deploy New ContractSOLIDITY CONTRACT SOURCE CODE field and select the contract PayEmployees to deploy.AMOUNT field to however much you want to send to the smart contract initially.
Contracts -> Custom Contracts and select your smart contract.withdraw() in this case) and click Execute. The smart contract will send the Ether and employee wallet balance should update in a minute or two.That's it for the Getting Started With Smart Contracts. Let's hope you enjoyed and understood how the pieces come together. Feel free to comment any improvements or doubts you have.