The Capital
Published in

The Capital

Getting Started With Ethereum Smart Contract Development

By Alibaba Cloud on Altcoin Academy

An Ethereum contract consists of a code string and data on a specific account address of an Ethereum blockchain. Contract accounts not only can communicate with each other, but they can also execute almost all of the Turing Complete computations available now. The contract code on an Ethereum blockchain is in a specific binary form, which is known as Ethereum Virtual Machine (EVM) binary code.

However, contracts are usually developed and written in some sort of advanced language, which is translated into binary code and uploaded to the blockchain. Existing Ethereum advanced development languages are JavaScript-like Solidity, Python-like Serpent, and Lisp-like LLL. This article will be using the first of these languages, Solidity.

Solidity is an object-oriented advanced Ethereum development language. Influenced by C++, Python, and JavaScript, it supports static types, inheritance, class libraries, and complex custom features. A typical contract development process includes writing, compiling, publishing, and calling.

The Eth Command Line Tool Geth

The Ethereum network command line client provides the Go-based Geth and C++-based Eth command-line tools. Geth is mainly used for Web development and Dapp front-end construction, while Eth is mainly used for GPU mining. But besides these differences, the two functions are almost identical. This article will use Geth because it is both easy-to-use and relatively widely used.

To begin this tutorial, let’s first install and start ethereum. You can install ethereum using the following actions and using brew with the following command.

brew tap ethereum/ethereum
brew install ethereum

Then, run ethereum with the following command:

geth console

By default, you will be connected to the Ethereum main network. The main network is slow and expensive, and transfers, the deployment of contracts, and calls to contracts consume Ether (ETH), so it cannot be directly used for development. As a result, you’ll want to build a private test network. A private test network needs to be set up, of which you are the only member. You are responsible for all the tasks, such as block generation, transaction verification, and smart contract execution. This helps to develop contracts at a low cost, simply and quickly.

You can use genesis.json to initialize the Genesis block, and set the datadir Directory:

geth --datadir ~/.ethereum_private init ~/dev/genesis.json

The genesis.json is as follows:

"config": {
"chainId": 12345,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
"nonce": "0x0000000000000033",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xffffffff",
"difficulty": "0x100",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": {}

In the following, the chainid and gaslimit configurations are specified. The initialization submission result is as follows:

INFO [02-13|16:08:23] Maximum peer count                       ETH=25 LES=0 total=25
INFO [02-13|16:08:23] Allocated cache and file handles database=/Users/shanyao/.ethereum_private/geth/chaindata cache=16 handles=16
INFO [02-13|16:08:23] Writing custom genesis block
INFO [02-13|16:08:23] Persisted trie from memory database nodes=0 size=0.00B time=7.737µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [02-13|16:08:23] Successfully wrote genesis state database=chaindata hash=76bc36…4efba1
INFO [02-13|16:08:23] Allocated cache and file handles database=/Users/shanyao/.ethereum_private/geth/lightchaindata cache=16 handles=16
INFO [02-13|16:08:23] Writing custom genesis block
INFO [02-13|16:08:23] Persisted trie from memory database nodes=0 size=0.00B time=1.16µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [02-13|16:08:23] Successfully wrote genesis state database=lightchaindata hash=76bc36…4efba1

Next, start the private network with the datadir, and bind a console through the inter-process communication path (ipc path), as shown below:

geth --fast --cache 512 --ipcpath ~/Library/Ethereum/geth.ipc --networkid 12345 --datadir ~/.ethereum_private  console

The result is as follows:

INFO [02-13|16:09:20] Maximum peer count                       ETH=25 LES=0 total=25
INFO [02-13|16:09:20] Starting peer-to-peer node instance=Geth/v1.8.2-stable/darwin-amd64/go1.10
INFO [02-13|16:09:20] Allocated cache and file handles database=/Users/shanyao/.ethereum_private/geth/chaindata cache=384 handles=1024
WARN [02-13|16:09:20] Upgrading database to use lookup entries
INFO [02-13|16:09:20] Database deduplication successful deduped=0
INFO [02-13|16:09:20] Initialised chain configuration config="{ChainID: 123456 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [02-13|16:09:20] Disk storage enabled for ethash caches dir=/Users/shanyao/.ethereum_private/geth/ethash count=3
INFO [02-13|16:09:20] Disk storage enabled for ethash DAGs dir=/Users/shanyao/.ethash count=2
INFO [02-13|16:09:20] Initialising Ethereum protocol versions="[63 62]" network=12345
INFO [02-13|16:09:20] Loaded most recent local header number=0 hash=76bc36…4efba1 td=256
INFO [02-13|16:09:20] Loaded most recent local full block number=0 hash=76bc36…4efba1 td=256
INFO [02-13|16:09:20] Loaded most recent local fast block number=0 hash=76bc36…4efba1 td=256
INFO [02-13|16:09:20] Regenerated local transaction journal transactions=0 accounts=0
INFO [02-13|16:09:20] Starting P2P networking
INFO [02-13|16:09:22] UDP listener up self=enode://42b0eec728cad819259d9685807bf78105450b6b28cd39d70417aa65ffebd3ac744b63d0446174bc657c9a42de2f0f9bc0f9589998c960177b844d5a962d8da9@[::]:30303
INFO [02-13|16:09:22] RLPx listener up self=enode://42b0eec728cad819259d9685807bf78105450b6b28cd39d70417aa65ffebd3ac744b63d0446174bc657c9a42de2f0f9bc0f9589998c960177b844d5a962d8da9@[::]:30303
INFO [02-13|16:09:22] IPC endpoint opened url=/Users/shanyao/Library/Ethereum/geth.ipc
Welcome to the Geth JavaScript console!instance: Geth/v1.8.2-stable/darwin-amd64/go1.10
modules: admin: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>

Now, the local private Ethereum network has been started. Now that that’s been done, you can view the network. To do so, enter admin to view the network information, as shown below:

> admin
datadir: "/Users/shanyao/.ethereum_private",
nodeInfo: {
enode: "enode://42b0eec728cad819259d9685807bf78105450b6b28cd39d70417aa65ffebd3ac744b63d0446174bc657c9a42de2f0f9bc0f9589998c960177b844d5a962d8da9@[::]:30303",
id: "42b0eec728cad819259d9685807bf78105450b6b28cd39d70417aa65ffebd3ac744b63d0446174bc657c9a42de2f0f9bc0f9589998c960177b844d5a962d8da9",
ip: "::",
listenAddr: "[::]:30303",
name: "Geth/v1.8.2-stable/darwin-amd64/go1.10",
ports: {
discovery: 30303,
listener: 30303
protocols: {
eth: {
config: {...},
difficulty: 256,
genesis: "0x76bc36aeb54afba3cb6dc2a5d13818edabeb7f119f8bf61ee127854b624efba1",
head: "0x76bc36aeb54afba3cb6dc2a5d13818edabeb7f119f8bf61ee127854b624efba1",
network: 12345
peers: [],
addPeer: function(),
clearHistory: function(),
exportChain: function(),
getDatadir: function(callback),
getNodeInfo: function(callback),
getPeers: function(callback),
importChain: function(),
removePeer: function(),
sleep: function*bridge).Sleep-fm(),
sleepBlocks: function*bridge).SleepBlocks-fm(),
startRPC: function(),
startWS: function(),
stopRPC: function(),
stopWS: function()

Then, you can view your node URL, as follows:

> admin.nodeInfo.enode

Note: You need to enter web3 to view all commands and structures. The prefixes of these commands are web3, which means that the effect of entering admin is the same as that of entering web3.admin.

Next, you can create an account:

> personal.newAccount("pk1")
> personal.newAccount("pk2")

The primary key here is your account password, which you will need to remember and save somewhere as you cannot recover it once it is lost.

Next, you can view the account:

> eth.accounts
["0xfb6565558c9fb3ef0eb657d5540bcd2859824e7f", "0x9652670122f63ea19398f93d088ccb458b16cbf7"]
> eth.accounts[0]

The first account created is usually called the primary account.

Now Check the balance:

> var primaryAccount = web3.eth.accounts[0]
> web3.eth.getBalance(primaryAccount)

As you can see from the results, the current balance of the account is 0. Let’s start the miner with the web3.miner.start() command, and dig for a while to earn some ETH:

> web3.miner.start()
INFO [02-13|16:29:24] Updated mining threads threads=0
INFO [02-13|16:29:24] Transaction pool price threshold updated price=18000000000
INFO [02-13|16:29:24] Starting mining operation
> INFO [02-13|16:29:24] Commit new mining work number=1 txs=0 uncles=0 elapsed=187.297µs
INFO [02-13|16:29:27] Successfully sealed new block number=1 hash=f59c04…83a194
INFO [02-13|16:29:27] ? mined potential block number=1 hash=f59c04…83a194
INFO [02-13|16:29:27] Commit new mining work number=2 txs=0 uncles=0 elapsed=113.91µs
INFO [02-13|16:29:27] Successfully sealed new block number=2 hash=09f545…b0230d
INFO [02-13|16:29:27] ? mined potential block number=2 hash=09f545…b0230d

After a while, open another window and stop mining:

ali-186590cc4a7f-2:ethereum shanyao$ geth attach
Welcome to the Geth JavaScript console!instance: Geth/v1.8.2-stable/darwin-amd64/go1.10
coinbase: 0xfb6565558c9fb3ef0eb657d5540bcd2859824e7f
at block: 99 (Wed, 13 Feb 2019 16:31:07 CST)
datadir: /Users/shanyao/.ethereum_private
modules: admin: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> web3.miner.stop()

Next, check the account balance again:

> web3.eth.getBalance(primaryAccount)

Create A Contract With The Command Line Tool

First, let’s write. To create a contract with the command line tool, you’ll want to first create a simple “hello world” contract. The code is as follows:

pragma solidity >=0.4.22 <0.6.0;contract Mortal {
/* Define variable owner of the type address */
address owner; /* This constructor is executed at initialization and sets the owner of the contract */
constructor() public { owner = msg.sender; } /* Function to recover the funds on the contract */
function kill() public { if (msg.sender == owner) selfdestruct(msg.sender); }
}contract Greeter is Mortal {
/* Define variable greeting of the type string */
string greeting; /* This runs when the contract is executed */
constructor(string memory _greeting) public {
greeting = _greeting;
} /* Main function */
function greet() public view returns (string memory) {
return greeting;

From the above, we can see that two contracts, Greeter and Mortal, exist. Greeter inherits from Mortal. In addition to the Kill function of Mortal, it has also added Greet function. It should be noted that the contract in Ethereum is immortal and uncontrolled by default. That is, once the contract is deployed on the blockchain, even the author of the contract no longer has the privilege to control the contract. The contract is defined by the author, but the execution of the contract and the services it provides are supported by the entire Ethereum network. As long as the entire network still exists, the contract will continue to exist and run. The contract will not disappear unless a self-destruction program is written and triggered.

The next step is to compile. Currently, the most convenient way to develop a contract is to use online IDE REMIX. After you paste in the code, it is automatically compiled as follows:

Pay attention to the ABI, ByteCode, and other key information in the Details of the compilation results on the right. The ABI (Application Binary Interface) is as follows:

"constant": false,
"inputs": [],
"name": "kill",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
"constant": true,
"inputs": [],
"name": "greet",
"outputs": [
"name": "",
"type": "string"
"payable": false,
"stateMutability": "view",
"type": "function"
"inputs": [
"name": "_greeting",
"type": "string"
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"

The next step is to deploy. Specifically, WEB3DEPLOY is the JS code of the contract to deploy, which is as follows:

var _greeting = "hello world!"; /* var of type string here */ ;
var greeterContract = web3.eth.contract([{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_greeting","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
var greeter =
from: web3.eth.accounts[0],
data: '0x608060405234801561001057600080fd5b506040516103c73803806103c78339810180604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600190805190602001906100dc9291906100e3565b5050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610230806101976000396000f3fe608060405260043610610046576000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b51461004b578063cfae321714610062575b600080fd5b34801561005757600080fd5b506100606100f2565b005b34801561006e57600080fd5b50610077610162565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100b757808201518184015260208101905061009c565b50505050905090810190601f1680156100e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610160573373ffffffffffffffffffffffffffffffffffffffff16ff5b565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101fa5780601f106101cf576101008083540402835291602001916101fa565b820191906000526020600020905b8154815290600101906020018083116101dd57829003601f168201915b505050505090509056fea165627a7a7230582083829c23804682d77517133b1aba64edd8cb8cc98a0f9cd40fc419024eb92ce00029',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);

Paste the code into the Geth window, and submit it to the private blockchain network. Before that, you need to unlock the account, as follows:

> personal.unlockAccount(web3.eth.accounts[0],"pk1")

Otherwise, the following error occurs: Error: authentication needed: password or unlock undefined. The result of deploying the contract is as follows:

INFO [02-13|17:15:47] Submitted contract creation              fullhash=0x5cafc176adea94dafee6ae1a6daa8b1ece894666ccac85f7858b16af5e15cdbe contract=0x579756a30442b508e2F6A0a4b4D1F4d871f9B906

This indicates that the contract creation transaction has been submitted, but the blockchain has not yet been mined at this time, so the transaction has not been packaged into the blockchain, and the entire blockchain network cannot be seen. Here, you must manually start mining again (mining is carried out continuously on the main network without stopping. The private test network here only has one node. For a clear demonstration, you need to manually start or stop mining each time). It can be seen in a few seconds:

Contract mined! address: 0x579756a30442b508e2f6a0a4b4d1f4d871f9b906 transactionHash: 0x5cafc176adea94dafee6ae1a6daa8b1ece894666ccac85f7858b16af5e15cdbe

This indicates that the contract has been deployed to the blockchain network. You can check and confirm through eth.getCode(greeter.address):

> eth.getCode(greeter.address)

Now, the contract can be executed.

Now, the next step is to call, which you can do as follows:

> greeter.greet();
"hello world!"

This call process does not change the blockchain state, so it returns immediately and does not consume gas.

The last step is to clean up. The contract code will be permanently stored on the blockchain unless it is self-destroyed. Therefore, abandoned contracts need to be destroyed, which requires sending transactions to the blockchain and paying for execution. For example:

> personal.unlockAccount(web3.eth.accounts[0],"pk1")
> greeter.kill.sendTransaction({from:eth.accounts[0]})
INFO [02-13|19:43:17] Submitted transaction fullhash=0xd66e3f444948f6bc7dfbfda1fb680c29c8173b061212d2457ef5553c71e8600c recipient=0x579756a30442b508e2F6A0a4b4D1F4d871f9B906

View the contract code again, as shown below:

> eth.getCode(greeter.address)

With that finished, the contract code has been cleared.


Through learning about the general process of Ethereum contract development in this blog, you now have an understanding of the general process of Ethereum contracts, and share a basic understanding. For more in-depth tutorials, see Ethereum official documentation.


  1. Building a smart contract using the command line
  2. Command line tools for the Ethereum Network
  3. ETH docs (contracts)
  4. Solidity docs

Original Source




A publishing platform for professionals in business, finance, and tech

Recommended from Medium

50 Shades of Staking: Part II — Away from General Purpose Blockchains. The case of Cosmos Network

EOS Amsterdam To Join Telos

Rangers Protocol: A Blockchain Platform For The Virtual World Offering A Full Vertical Solution.

Eleven Finance — token structure and fee model.

Axelar for newbies [ENG Version]

Gamestate Launches Multi-Chain Integrated NFT Metaverse Project with Polygon Studios!

What is DAO and how to become a member of a decentralized community by the example of BaksDAO…

AMA recap of Razor and Knit finance

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:

More from Medium

Bridges and how they work

IntoTheBlock signals are now available on WazirX

5 Minutes Cryptocurrency: L1 Blockchain — Solana

What’s in Store for Blockchain in 2022