How to deploy SmartContract

Introduction

We’re going to deploy an Ethereum-compatible Smart Contract on Sirius (the Lightstreams test network).

Background

Lightstreams network is a fully Ethereum-compatible network. Every tool, manual, or resource that works on Ethereum should also work on the Ligthstreams network. If something doesn’t work or if you are blocked, please let us know on via our support chat on the website!

In this section we are going to use our experience to write some simple instructions to deploy your first smart contract into Lightstreams blockchain.

Node Initialization

First, in order to deploy a smart contract we need to have a fully-synchronized node running locally. In case you didn’t do it yet, see the lightchain node setup guide.

Alternatively, you could also connect to our open via the HTTP-RPC endpoints (see the HTTP API:

  • Mainnet: https://node.mainnet.lightstreams.io
  • Testnet: https://node.sirius.lightstreams.io

We recommend having a local node to get a better development experience.

Solidity

Solidity is an object-oriented, high-level language for implementing smart contracts. You can read more about this particular programming language in the official documentation.

There are pluggings to support Solidity code for most of the popular IDE such as JetBrains IDEA, Sublime Text or emacs. Also you can find a very good online editor provided by Ethereum project called Remix. Remix also supports testing, debugging and deploying of smart contracts and much more.

For testing propose we are going to write a very simple HelloWorld.sol:

pragma solidity ^0.5.0;

contract HelloBlockchainWorld {
    constructor() public {
    }

    function sayHello() public pure returns (string memory message) {
        return "hello";
    }
}

Compilation

In order to deploy and then interact with the written smart contract, we need to compile it to be deployed into our EVM (Ethereum Virtual Machine).

As a result of the compilation, you should get two things: - ABI: Application Binary Interface, is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction. - Bytecode: Assembly representation of the contract in hexadecimal format.

How do we compile our smart contract? There are several alternatives that we will show you next.

Option 1: Solidity Compiler

Solidity project provides a binary compiler, solc, to compile solidity code. You can find instructions about how to install it on every popular OS in their documentation.

Once you completed the installation steps you should be capable to run the following command on a terminal to obtain the compiler version installed.

$> solc --version

solc, the solidity compiler commandline interface
Version: 0.5.0+commit.1d4f565a.Linux.g++

Assuming we stored our HelloWorld example in /tmp/example/helloworld.sol, first we are going to create a destination folder for the build elements:

$> mkdir /tmp/example/build

Then, we execute the next:

$> solc --abi --bin /tmp/example/helloworld.sol -o /tmp/example/build/ --overwrite

As the result from the above command it was generated two files, one containing the ABI representation of the contract HelloBlockchainWorld.abi and another one with the bytecode HelloBlockchainWorld.bin.

/tmp/example/build/
├── HelloBlockchainWorld.abi
└── HelloBlockchainWorld.bin

Option 2: Remix

Another alternative is to use the online tool of Remix. For that, we need to: 1. Paste our helloworld.sol code 2. Click on Start to compile and wait for compilation to finish. 3. Click on ABI and paste the clipboard content into a file named HelloBlockchainWorld.abi. 4. Click on Bytecode and paste the clipboard content into a file named HelloBlockchainWorld.bin.

login

Option 3: NodeJS & Truffle

Truffle is a testing framework for Ethereum written in javascript. Truffle provides a full set of tools to compile, deploy and debug smart contracts using the Ethereum Virtual Machine (EVM).

To install truffle, and assuming you already got npm installed in your system, you only need to run the follow:

$> npm install -g truffle

Once truffle is installed you have to create a new empty “project”.

$> truffle init /tmp/example/truffle

Now you should have the following folder structure under /tmp/example/truffle

├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
└── truffle-config.js

inside truffle-config.js you have to define which version of solidity compiler you want to use, along with other solidity options, but for now we are only going to define a fixed version of solidity according to the version we defined in the smart contract implementation

...
// Configure your compilers
  compilers: {
    solc: {
      version: "0.5.0",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    }
  }
...

Truffle will compile every contract under ‘/contracts’, therefore we have to copy/move our helloworld.sol file into /tmp/example/truffle/contracts

$> cp /tmp/example/helloworld.sol /tmp/example/truffle/contracts/

We remove the unnecessary file /migrations/1_initial_migration.js:

$> rm migrations/1_initial_migration.js

And at the end we run the compilation:

$> truffle compile


Compiling your contracts...
===========================
> Compiling ./contracts/helloworld.sol
> Artifacts written to /tmp/example/truffle/build/contracts
> Compiled successfully using:
   - solc: 0.5.0+commit.1d4f565a.Emscripten.clang

As result of above command we will obtain a json file build/contracts/HelloBlockchainWorld.json which contains the abi and the bytecode.

cat build/contracts/HelloBlockchainWorld.json | jq '.abi'
[
  {
    "inputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  ...
]
cat build/contracts/HelloBlockchainWorld.json | jq '.bytecode'
"0x608060405234801561001057600080fd5b5061013f806100206000396000f...."

Note: jq is a tool to extract json content in bash

Deploy

In order to deploy an smart contract we will need to have an unlock account holding enough funds. To unlock the account we are going to use geth.

We attach geth to our running local node and execute personal.unlockAccount() over the account we desire to unlock.

$> geth attach http://localhost:8545

Welcome to the Geth JavaScript console!

instance: ./v1.8.27/linux-amd64/go1.10.3
 modules: debug:1.0 eth:1.0 net:1.0 personal:1.0 rpc:1.0 web3:1.0

> personal.unlockAccount("0xc916cfe5c83dd4fc3c3b0bf2ec2d4e401782875e")
Passphrase: 
true

Option 1: Console (Geth)

First, we need to attach our terminal to our node

$> geth attach http://localhost:8545

Note: Every following statement is executed on geth terminal

We assign the content of the file generated during the compilation of the smart contract to two variables.

> var bin = <"HelloBlockchainWorld.bin" file content>
> var abi = <"HelloBlockchainWorld.abi" file content>

Create a contract template object based on the abi and calculate the estimated gas for the transaction of deployment:

var contractTemplate = web3.eth.contract(abi);
var estimatedGas = eth.estimateGas({data: "0x" + bin})

Send contract deploy transaction, The contract deployment is an asynchronous call therefore in order to track the process, we will add a callback function which logs the execution progress:

contractTemplate.new({from: "0xc916cfe5c83dd4fc3c3b0bf2ec2d4e401782875e", data: "0x" + bin, gas: estimatedGas}, 
  function(err, contract){  
   if(err){
     console.log("Error sending transaction: ", err);
     return;
   }
   if(!contract.address){
     console.log("Transaction hash: " + contract.transactionHash)
     return;
   }
   console.log("Contract deployed at: " + contract.address);
  });

Option 2: Remix

Remix also integrates the utilities required to deploy and interact with smart contracts. In case you want to connect to the node running on your local machine you will need to authorized by the usage of the following flags --rpcvhost and --rpccorsdomain:

$> lightchain run --datadir=${HOME}  --rpc --rpcaddr 0.0.0.0 -rpcapi eth,net,web3,personal,debug --rpccorsdomain=* --rpcvhosts=localhost

Now we have our environment ready we go back to Remix dashboard and click in Run. Select Web3 Provider from the Environment selector and paste the local rpc address http://localhost:8545. from account unlocked at the beginning.

Click Deploy and if everything went successfully you will see a transaction receipt as the one on the next screenshot.

remix

Option 3: Truffle

In truffle-config.js you need to update the development network and modify it as required, to connect to a running ethereum node. Also we indicate which from account is going to be use as default message sender for every transaction.

...
  networks: {
    development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
      from: "0xc916cfe5c83dd4fc3c3b0bf2ec2d4e401782875e",
      gasPrice: "500000000000"
    },
    ...
  }
...

SUPER IMPORTANT NOTE: Lightchain networks use 500 gwei as gasPrice

We create a new migration file /migrations/2_hello_world.js with the following code:

const HelloBlockchainWorld = artifacts.require("HelloBlockchainWorld");

module.exports = function(deployer) {
  deployer.deploy(HelloBlockchainWorld);
};

And finally we trigger the deployment:

$> truffle deploy --reset --network=development

Note: Remember that the from account MUST unlock it before we run the deployment. You can see how to do it at the top of this section.

Output:

2_hellow_world.js
=================

   Deploying 'HelloBlockchainWorld'
   --------------------------------
   > transaction hash:    0x734944fc76af2c71bfee528c94abba2a5c71575140fede9ab26e8ee332fde3e2
   > Blocks: 0            Seconds: 0
   > contract address:    0x0f5d5bEb0766C7a26198Bf82EBF1B2df3dEA09e5
   > block number:        90
   > block timestamp:     1560868779
   > account:             0xc916Cfe5c83dD4FC3c3B0Bf2ec2d4e401782875e
   > balance:             299999995.447825
   > gas used:            104043
   > gas price:           500 gwei
   > value sent:          0 ETH
   > total cost:          0.0520215 ETH

   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0520215 ETH

From the output above we can see that our HelloWorld smart contract was deployed at the address 0x0f5d5bEb0766C7a26198Bf82EBF1B2df3dEA09e5 and the deployment cost was 0.052 ETH.

Congratulations! You have just deployed your first Lightstreams Smart Contract!! Well done!