Projects

The Complete Tutorial On Getting Started With Smart Contracts On Ethereum

The Complete Tutorial On Getting Started With Smart Contracts On Ethereum

img

Every download, install, framework, tool, and process you will need to get started. This tutorial assumes you have an understanding of Ethereum, Smart Contracts, and how to code.


Download and install Node.js

Go to https://nodejs.org/en/ and download the version for Latest Features on the right. After it’s done downloading, install it.

Verify you have node and npm installed:

1
2
node -v
// v10.1.0
1
2
npm -v
// v6.0.1

Download and install an IDE

You can use any text editor or IDE but the recommended ones for Solidity are Visual Studio Code and Atom. I use VS Code.

Go to https://code.visualstudio.com/ and download Stable Build. After it’s done downloading, open it.

Click the last icon on the left side bar to open Extensions. Search for solidity and choose the one by Juan Blanco. Install it. Reload VS Code to use the extension.

img

Here are my VS Code preferences, go to File > Preferences > Settings and copy the below into User Settings:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"editor.dragAndDrop": false,
"editor.fontSize": 12,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.formatOnPaste": true,
"editor.wordWrap": "on",
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
"explorer.confirmDragAndDrop": false,
"explorer.confirmDelete": false,
"files.autoSave": "onFocusChange",
"workbench.colorTheme": "Default Light+",
"solidity.enabledAsYouTypeCompilationErrorCheck": true,
"solidity.linter": "solium",
"solidity.packageDefaultDependenciesContractsDirectory": "",
"solidity.packageDefaultDependenciesDirectory": "",
"solidity.validationDelay": 1500
}

If you’re using Windows, skip to Install Truffle. If you’re using Mac, follow this step to add VS Code to your PATH, which allows launching VS Code from the command line.

Open VS Code. Open the Command Palette (⇧⌘P), type shell command and click Shell Command: Install ‘code’ command in PATH. Now you can open a directory using code .


Install Truffle

Truffle is the most popular development framework for Ethereum.

1
npm install -g truffle

Verify you have truffle installed:

1
2
3
truffle v
// Truffle v4.1.8 (core: 4.1.8)
// Solidity v0.4.23 (solc-js)

Truffle Boxes

Truffle Boxes are helpful boilerplates that should be taken advantage of instead of starting from scratch, such as a react app or a coin example. http://truffleframework.com/boxes/

  1. Create a new directory for your Truffle project:
1
2
mkdir MetaCoin
cd MetaCoin

\2. Download (“unbox”) the MetaCoin box:

1
truffle unbox metacoin

\3. Open the directory:

1
code .

Now you should have a project structure with the following items:


Using Truffle and Open Zeppelin to create an ERC20 Token

Instead of using a Truffle box we can also initialize an empty Truffle project. Here is a link to the repo: https://github.com/ricochen/ERC20Token

Let’s leave the MetaCoin directory and create a new one:

1
2
3
cd ..
mkdir ERC20Token
cd ERC20Token

Initialize the Truffle project: (directory MUST be empty)

1
truffle init

Open the directory:

1
code .

You should see a similar directory structure as the MetaCoin box. truffle init creates the skeleton and necessary files for a Truffle project.

You will see that Migrations.sol has errors, this is because of the Solidity extension we installed. Migrations.sol is using outdated syntax compared to our linter rules, fix them by using 4 indentations instead of 2, and changing

1
function Migrations() public {
1
owner = msg.sender;
1
}

to

1
constructor() public {
1
owner = msg.sender;
1
}

Open Zeppelin

OpenZeppelin is a library for writing secure Smart Contracts on Ethereum. https://github.com/OpenZeppelin/openzeppelin-solidity. OpenZeppelin is meant to provide secure, tested and community-audited code, however, nothing is 100% secure so make sure to thoroughly test and audit your code. Take a look in their contracts folder and become familiar with the code as they have become a standard for writing Smart Contracts. We will be using their implementation of an ERC20 Token.

To install the OpenZeppelin library, run the following in your Solidity project root directory:

1
2
npm init -y
npm install -E openzeppelin-solidity

Coding a Smart Contract:

Create a new file under /contracts and name it ERC20Token.sol , the .sol means it’s a Solidity file. Write the Solidity version we will be using at the top:

1
pragma solidity ^0.4.23;

Import the Open Zeppelin dependencies for our ERC20 Token:

1
import "openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol";

You will see an error with the import. Currently, the only way to make the Open Zeppelin import work with our Solidity extension is to update our preferences. This will likely be fixed in the future. In VS Code, type ctrl + comma to open User Settings and add this and save:

1
2
"solidity.packageDefaultDependenciesContractsDirectory": "",
"solidity.packageDefaultDependenciesDirectory": "",

Write the ERC20 Token contract:

1
2
3
4
5
6
7
/**
* @title ERC20Token
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
* Note they can later distribute these tokens as they wish using `transfer` and other
* `StandardToken` functions.
*/
contract ERC20Token is StandardToken {
1
2
3
string public constant name = "ERC20Token"; // solium-disable-line uppercase
string public constant symbol = "ERC"; // solium-disable-line uppercase
uint8 public constant decimals = 18; // solium-disable-line uppercase
1
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals));
1
2
3
4
5
6
7
8
9
    /**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor() public {
totalSupply_ = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
emit Transfer(0x0, msg.sender, INITIAL_SUPPLY);
}
}

We’re going to make it a simple ERC20 Token which includes a name, symbol, decimal, and initial supply. https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/examples/SimpleToken.sol.

Writing Tests

Next we’re going to write tests for our ERC20 Token. Create a new file under /test and name it ERC20Token.test.js :

1
const ERC20Token = artifacts.require('ERC20Token');
1
2
3
contract('ERC20Token', accounts => {
let token;
const creator = accounts[0];
1
2
3
beforeEach(async function () {
token = await ERC20Token.new({ from: creator });
});
1
2
3
4
it('has a name', async function () {
const name = await token.name();
assert.equal(name, 'ERC20Token');
});
1
2
3
4
it('has a symbol', async function () {
const symbol = await token.symbol();
assert.equal(symbol, 'ERC');
});
1
2
3
4
it('has 18 decimals', async function () {
const decimals = await token.decimals();
assert(decimals.eq(18));
});
1
2
3
it('assigns the initial total supply to the creator', async function () {
const totalSupply = await token.totalSupply();
const creatorBalance = await token.balanceOf(creator);
1
2
3
    assert(creatorBalance.eq(totalSupply));
});
});

Run the test:

1
truffle test

You will see the following output:

1
2
3
4
5
Contract: ERC20Token
✓ has a name
✓ has a symbol
✓ has 18 decimals
✓ assigns the initial total supply to the creator
1
4 passing (356ms)

Additional files

Create a new file in the root directory and name it .gitignore. We will use it to ignore our /build and /node_modules folders when committing to GitHub.

1
2
build/
node_modules/

Create a new file in the root directory and name it .gitattributes. This will be used to add syntax color to our .sol files on GitHub.

1
*.sol linguist-language=Solidity

Deploying to Ganache (Local)

Now that we have the contract and test finished, we will migrate and deploy the contract using Ganache, a personal blockchain for Ethereum development that runs on your desktop. Ganache has a UI that you can download and interact with, as well as a command line option. We will be using the latter, ganache-cli. https://github.com/trufflesuite/ganache-cli/

1
npm install -g ganache-cli

You may have noticed there are two truffle config files. The reason is that in Windows there is a naming conflict with truffle.js. To fix this we can simply delete truffle.js and use truffle.config.js which will work for both Windows and Mac.

Add the ganache-cli network to our truffle-config.js file:

1
2
3
4
5
6
7
8
9
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
}
}
};

Run ganache-cli:

1
ganache-cli

Ganache will generate 10 test accounts which each have 100 ether by default, and are unlocked for us to use.

Open another command line and go to our ERC20 Token directory and compile the contracts:

1
truffle compile

You will see the following output:

1
2
3
4
5
6
7
8
Compiling ./contracts/ERC20Token.sol...
Compiling ./contracts/Migrations.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol...
Writing artifacts to ./build/contracts

You will see a /build folder that contains our compiled contracts in JSON.

We will need a migrations script to help us deploy our ERC20 Token contract to the blockchain. Create a new file under /migrations and name it 2_deploy_contracts.js:

1
var ERC20Token = artifacts.require("./ERC20Token.sol");
1
2
3
module.exports = function(deployer) {
deployer.deploy(ERC20Token);
};

Migrate and deploy the contracts to our development blockchain:

1
truffle migrate --network development

You will see the following output:

1
Using network 'development'.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x4f87ddd3c299752294356431998d511e1879b08d3a6b5acff36d4727f92690e0
Migrations: 0x90678eeba892762d1d456ae58872c94eba2c2e52
Saving successful migration to network...
... 0x09bbbf050c015ed94a48a92f842605b9f2f857a18cc2c90bd6c9b5b37b630aa1
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying ERC20Token...
... 0x94e4617012532bcd90a9f92ef349fd5990430596dd4e1c2733c543ebb1d35c0b
ERC20Token: 0x395892c139c59533941c87a6dad33e2889fd5de3
Saving successful migration to network...
... 0x06dc8833243d8fb100c8bd2117ad246721488273eac79bab40a4c70437262dc2
Saving artifacts...

Run the following to start Truffle’s console, which will allow us to interact and test the newly deployed ERC20 Token.

1
truffle console --network development

Store the ERC20 Token instance in a variable:

1
ERC20Token.deployed().then(inst => ERC20TokenInstance = inst)

Check the ERC20 Token instance name and total supply:

1
ERC20TokenInstance.name()
1
// 'ERC20Token'
1
ERC20TokenInstance.totalSupply().then(function(i) {totalSupply = i})
1
// undefined
1
totalSupply.toNumber()
1
// 1e+22

Deploying to Rinkeby (Testnet)

Geth is the command line interface for running a full ethereum node implemented in Go. We will use Geth to deploy to the Rinkeby Testnet.

For Windows:

Go to https://geth.ethereum.org/downloads/ to download and install Geth. Check Geth and Development tools.

For Mac:

Install Homebrew:

1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Install Geth:

1
2
brew tap ethereum/ethereum
brew install ethereum

Check Geth is installed:

1
geth version
1
2
3
4
5
6
7
8
9
// Geth
Version: 1.8.8-stable
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10.2
Operating System: darwin
GOPATH=
GOROOT=/usr/local/Cellar/go/1.10.2/libexec

Create a directory to store your blockchain files:

1
2
mkdir rinkeby
cd rinkeby

Initialize the genesis block:

1
2
curl -O https://www.rinkeby.io/rinkeby.json
geth --datadir=. init rinkeby.json

Download the Rinkeby blockchain:

1
geth --datadir=. --rpc --rinkeby --rpcapi "web3,eth,net,personal" --cache=1024

You will see the follow output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
INFO [05-14|21:08:37] Maximum peer count                       ETH=25 LES=0 total=25
INFO [05-14|21:08:37] Starting peer-to-peer node instance=Geth/v1.8.7-stable-66432f38/windows-amd64/go1.10.1
INFO [05-14|21:08:37] Allocated cache and file handles database=C:\\Users\\ricox\\Documents\\GitHub\\projects\\rinkeby\\geth\\chaindata cache=768 handles=1024
INFO [05-14|21:08:37] Persisted trie from memory database nodes=355 size=65.27kB time=467.9µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|21:08:37] Initialised chain configuration config="{ChainID: 4 Homestead: 1 DAO: <nil> DAOSupport: true EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: 1035301 Constantinople: <nil> Engine: clique}"
INFO [05-14|21:08:37] Initialising Ethereum protocol versions="[63 62]" network=4
WARN [05-14|21:08:37] Head state missing, repairing chain number=2263453 hash=24f662…e2ea0b
INFO [05-14|21:08:37] Rewound blockchain to past state number=2263053 hash=33b947…61815f
INFO [05-14|21:08:37] Loaded most recent local header number=2263453 hash=24f662…e2ea0b td=4237648
INFO [05-14|21:08:37] Loaded most recent local full block number=2263053 hash=33b947…61815f td=4236848
INFO [05-14|21:08:37] Loaded most recent local fast block number=2263453 hash=24f662…e2ea0b td=4237648
INFO [05-14|21:08:37] Loaded local transaction journal transactions=6 dropped=0
INFO [05-14|21:08:37] Regenerated local transaction journal transactions=6 accounts=1
WARN [05-14|21:08:37] Blockchain not empty, fast sync disabled
INFO [05-14|21:08:38] Starting P2P networking
INFO [05-14|21:08:40] UDP listener up self=enode://fdad6fb872dc90d587b0225a5b7f3c7d2d53efef6574415a1cf8f0c42da0791b80553a1753403d2c118b33a2b9cb474673e9c759394a92f1c0435edbaddf756f@76.102.174.73:30303
INFO [05-14|21:08:40] RLPx listener up self=enode://fdad6fb872dc90d587b0225a5b7f3c7d2d53efef6574415a1cf8f0c42da0791b80553a1753403d2c118b33a2b9cb474673e9c759394a92f1c0435edbaddf756f@76.102.174.73:30303
INFO [05-14|21:08:40] IPC endpoint opened url=\\\\.\\pipe\\geth.ipc
INFO [05-14|21:08:40] HTTP endpoint opened url=http://127.0.0.1:8545 cors= vhosts=localhost

To check the blockchain sync process, copy the IPC endpoint in bold (mine is \\\\.\\pipe\\geth.ipc, yours may be different). Open another command line and paste your IPC endpoint after geth attach.

1
geth attach \\\\.\\pipe\\geth.ipc

You will see the following output:

1
Welcome to the Geth JavaScript console!
1
2
instance: Geth/v1.8.7-stable-66432f38/windows-amd64/go1.10.1
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

Type eth.syncing to check the progress, this can take a few hours:

1
eth.syncing
1
2
3
4
5
6
7
// {
currentBlock: 35191,
highestBlock: 2290216,
knownStates: 68389,
pulledStates: 52406,
startingBlock: 0
}

Wait until the syncing is finished before moving on, it will output false:

1
eth.syncing
1
// false

Open another command line and go to your Rinkeby directory. Create a new account to use for Rinkeby, it will be stored in /keystore:

1
2
cd rinkeby
geth --datadir=. account new

Type in your password and repeat it, then you should receive your address:

1
2
3
4
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {f6e9dc98fe5d2951744967133b3c31765be657c1}

To check your accounts, go to the Geth JavaScript console tab and type:

1
2
eth.accounts
// ["0xf6e9dc98fe5d2951744967133b3c31765be657c1"]
1
2
eth.coinbase
// "0xf6e9dc98fe5d2951744967133b3c31765be657c1"

To check your balance:

1
2
eth.getBalance(eth.coinbase)
// 0

We’re going to need ETH to make transactions in Rinkeby. To request ETH from the Rinkeby faucet, we need to make a public post using Twitter, Facebook, or Google+.

I will use Google+, go to https://plus.google.com/ and make a public post with your address with the 0x prepended and without the quotes. Click the arrow to get the url such as: https://plus.google.com/105101964713106743199/posts/LC5VqAxZrcd

Copy this url and paste it into https://www.rinkeby.io/#faucet and click Give me Ether and choose 3 Ethers / 8 hours. You will have to wait 8 hours to request again using Google+. If the transaction was successful but something went wrong, use Twitter or Facebook using the same steps above so you don’t have to wait.

img

Wait one minute for the transaction to finish and verify your transaction with your Rinkeby address on Etherscan:
https://rinkeby.etherscan.io/address/0xf6e9dc98fe5d2951744967133b3c31765be657c1

img

Also verify through the Geth JavaScript console:

1
2
eth.getBalance(eth.coinbase)
// 3000000000000000000

Unlock your account, type your password and press enter:

1
2
3
4
personal.unlockAccount(eth.coinbase)
// Unlock account 0xf6e9dc98fe5d2951744967133b3c31765be657c1
// Passphrase:
// true

Open a new command line and open your ERC20 Token directory:

1
2
cd ERC20Token
code .

Add the Rinkeby network to your truffle-config.js file and replace from with your address:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
},
rinkeby: {
host: "localhost",
port: 8545,
network_id: "4", // Rinkeby ID 4
from: "0xf6e9dc98fe5d2951744967133b3c31765be657c1" // account from which to deploy
}
}
};

Migrate and deploy the contracts to Rinkeby Testnet:

1
truffle migrate --network rinkeby

You will see the following output:

1
Using network 'rinkeby'.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x657f08c640c5427b5c6ceba4b0a357a990540b117173ec8152d7c95ce1ae01ed
Migrations: 0xd1ac4c1f8695ff626ddc172080ebfa3c68b0ade9
Saving successful migration to network...
... 0xc4805b117afcb4541722b3428966f14389166bac7c39e3909f544c1634ee8da6
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying ERC20Token...
... 0x13da61f42445b7809700de645232e514b7757154ba030b4a962516c72d3716e9
ERC20Token: 0x17db24765fc009a5b42360ef500daf839f51a040
Saving successful migration to network...
... 0x8af12b2773de916acf8be3ec67a3ec4c1d0cb9a493ac675cc0910eef50fd6e52
Saving artifacts...

Wait a minute and verify it’s deployed on Etherscan: https://rinkeby.etherscan.io/address/0xf6e9dc98fe5d2951744967133b3c31765be657c1

img

For future uses with Rinkeby, save these commands:

Open one command line for Geth, replace with your address and type in your password after:

1
geth --datadir ./rinkeby --rpc --rinkeby --rpcapi "web3,eth,net,personal" --cache=1024 --unlock "0xacfa76dbd4a46d5497f8d657cfc8a343c69b584d"
1
2
// Unlocking account 0xacfa76dbd4a46d5497f8d657cfc8a343c69b584d | Attempt 1/3
Passphrase:

Open a second command line for the Geth JavaScript console, replace with your IPC endpoint:

1
2
geth attach \\\\.\\pipe\\geth.ipc
eth.syncing

Open a third command line for truffle:

1
2
truffle migrate --network rinkeby
truffle console --network rinkeby
1
2
ERC20Token.deployed().then(inst => ERC20TokenInstance = inst)
ERC20TokenInstance.name()


Read more

Bluzelle - Scalable Data Services for dApps

1
2
Author: Dillon Settle
General Inquiries: hello@decentral.solutions

Bluzelle - Scalable Data Services for dApps

WHAT IS IT?

Bluzelle combines the sharing economy with the token economy - renting individuals’ computer storage space to earn tokens while dApp developers use tokens to have their dApp’s data stored and managed.

Bluzelle is a decentralized, on-demand, scalable database service for dApps. To ensure developers get the highest throughput in performance, reliability and scalability, Bluzelle implements swarming technologies.

A swarm is a large group of nodes (computers) that work together to store and manage data. Nodes in these swarms can go down and new nodes can come up with minimal impact on the network.

Bluzelle fills a need to make the decentralized Internet complete, by improving efficiency and scale of data storage and management.

Bluzelle is NOT a blockchain. Blockchains, at the risk of giving a circular answer, are chains of blocks of data. Bluzelle is a database, and conceptually, not too different from common NoSQL databases.



Read more

[Case Study] Token Design

Overview

A US based security startup, commissioned Decentral Solutions to design an end-to-end digital identity solution that would enable customers to validate and share identity information. Traditionally this would involve sending ID documents over insecure channels (e.g. email) and expensive KYC and compliance processes. The client had a very tight timeframe for development.

Solution

Within a few months Decentral Solutions developed an end-to-end solution supporting KYC providers, issuers, 3rd party application developers, and end-users. Our team started by designing a backend for issuers allowing them to validate individual information and generate digital certificates. The backend relied on an HSM (Hardware Security Module) for digital signing of certificates.



Read more

[Case Study] Public Capped Sale

Overview

A Startup Incubator based in Silicon Valley faced a recurring challenge centered around getting their incubatee companies to scale. Decentral Solutions started an engagement centered around a blockchain solution to decentralized content creation.

Solution

Over the span of multiple weeks our team worked to make a broad, multi-faceted problem into a specific one. First we let the client fully define the problem in terms of his scope of expertise, which was building and scaling small startups. From those requirements we were able to provide a prototype whitepaper that details the necessary blockchain protocols needed to solve the content creation problem in each subdomain.


Read more

[Case Study] Smart Contract Audit Process

Overview

Decentral Solutions has worked with many customers to evaluate the security of their products and engineering practices. Smart contracts provide a way to programatically govern relationships between one or more entities without the need for a middleman. The security implications of this new paradigm are far reaching, leading to new classes of vulnerabilities in code. Vulnerabilities in smart contracts have cumulatively cost the cryptocurrency ecosystem hundreds of millions of dollars in losses. We help to identify security flaws in your contracts before they are deployed into a production environment.

Solution

Decentral Solutions sits down with the clients engineering team to understand their business, architecture, existing code base, engineering practices, etc.

We then write a detailed threat model including data flow diagrams, list of potential threats (details listed below), and mitigations. Finally we assisted customers in implementing changes to their code and their engineering practices to close the gaps.



Read more