In Building a Dapp on Ethereum Series Part 1 of this series, we had seen how to setup and communicate with an ethereum node in different ways. Now after setting up our node, we are ready to write a smart contract that will run on ethereum blockchain. Solidity and Vyper are two choices when it comes to programming languages to write smart contracts on ethereum blockchain. Vyper is being currently developed with intention that smart contracts will be formally verifiable(means any smart contract can be mathematically proved that it does what it says), But vyper is an experimental language which is still in active development phase and has lesser developers support in terms of tools and libraries. Solidity being popular in smart contract developer community will be our choice to write one.

Writing a Smart Contract in Solidity

Written below is a smart contract which will store hash of an IPFS file on to blockchain and then retrieve it back. we will discuss more about IPFS in Part 3 of this series.

    pragma solidity ^0.4.18;
    
    /**
     * @title IPFSHashStorage
     * @dev The IPFSHashStorage Contract provides basic hash storage against a account
     * and hash retrieval functions.
     */
    
    contract IPFSHashStorage {
        mapping (address => string) private storedHash;
        event HashUpdated (address user);
       
       /**
       * @dev store function writes hash in msg sender account 
       * @param hash of IPFS file
       */

        function store(string hash) public {
            storedHash[msg.sender] = hash;
            emit HashUpdated(msg.sender);
        }

       /**
       * @dev getStoredHash function reads hash from msg sender account
       * @return hash of IPFS file
       */

        function getStoredHash() public view returns(string hash) {
            return storedHash[msg.sender];
        }

    }

Now we will discuss above smart contract which stores and retrieves hash from blockchain in detail.

    pragma solidity ^0.4.18;

the above line tells that solidity compiler version should be 0.4.18 or greater but only until version 5.0.0. for more info view pragma .

    contract IPFSHashStorage {
        mapping (address => string) private storedHash;
        event HashUpdated (address user);

In above snippet, Contract and its state variable are defined, along with an event for logging. State variable is in form of mapping(similar to array) where hash will be stored against a address. Event will be used in smart contract for logging( whenever a hash is updated against a address).
To learn more about state variables and events read this documentation

      /**
       * @dev store function writes hash in msg sender account 
       * @param hash of IPFS file
       */

        function store(string hash) public {
            storedHash[msg.sender] = hash;
            emit HashUpdated(msg.sender);
        }

       /**
       * @dev getStoredHash function reads hash from msg sender account
       * @return hash of IPFS file
       */

        function getStoredHash() public view returns(string hash) {
            return storedHash[msg.sender];
        }

In above code snippet, function store does two things, first it maps input parameter hash with message sender's address and then logs it with help of a event. The other function getStoredHash simply retrieves hash against message sender's address. We will not go into depth of solidity contracts, which is left to readers to learn for themselves, for more read solidity documentation

Compiling a Smart Contract

There are different ways to compile a solidity smart contract, we will examine each one of them here. Source files of smart contract are saved with extension .sol

  1. Command line Solidity Compiler

    Download solc binaries for compiling solidity smart contracts or you can build and install solc compiler yourselves.
    usage : solc [options][inputfile]
       solc -o ./ --abi --bin ./IPFSHashStorage.sol

The above command takes input file IPFSHashStorage.sol in current directory and outputs two file IPFSHashStorage.abi and IPFSHashStorage.bin in current directory. Shortly we will look into what --abi and --bin command line options does.

  1. Solidity Compiler as a Node.js package

    Install solidity compiler as a Node.js package
     npm install -g solc

for more info view solc-js.

How to compile smart contracts using solc-js in Node.js

    const solc = require('solc')
    const fs = require('fs')
    var input = fs.readFileSync('./contracts/IPFSHashStorage.sol')
    var output = solc.compile(input.toString(),1)
    // bytecode
    var bytecode = output.contracts[':IPFSHashStorage'].bytecode
    // ABI
    var abi = output.contracts[':IPFSHashStorage'].interface
  1. Remix IDE

    Remix a browser-based compiler and IDE that enables users to build Ethereum contracts with Solidity language and to debug transactions. Remix IDE can connect to ethereum node via MetaMask chrome extension or can connect directly to any HTTP-RPC server.

Deploy a Smart Contract on Ethereum Blockchain

Once we have Bytecode and ABI from compiled source, we can deploy the contract to blockchain. Lets see how it is done.

  1. Deploy using web3.js and Node.js

        const Web3 = require('web3')
        const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"))
        var MyContract = web3.eth.contract(JSON.parse(abi))
        var gasEstimate = web3.eth.estimateGas({data: "0x"+bytecode})
        var myContractInstance = MyContract.new({
        from:web3.eth.accounts[0],
        data: "0x"+bytecode, 
        gas: gasEstimate}, function(err,contract){
            if(err) {
                console.log(err)
                return
            }
            if(contract.address) {
             console.log("MyContract deployed at address :" + contract.address)
            } else {
             console.log("MyContract is waiting to be mined at transaction hash:" + contract.transactionHash);
            }
        })
        
        // After contract deployment,address and transactionHash will get autofilled 
        myContractInstance.address
        myContractInstance.transactionHash
    
  2. Deploy using REMIX IDE

    You can use online REMIX IDE to even deploy contracts.

Interacting with Smart Contract using web3.js

Once we have deployed contract on to ethereum blockchain, we can interact with our contract using web3.js, below code snippet is continuation of previous code snippet.

    // Refer contract above for functions store & getStoredHash 
    var hash = 'QmWWQSuPMS6aXCbZKpEjPHPUZN2NjB3YrhJTHsV4X3vb2t'
    var account = web3.eth.accounts[0]
    // store function take hash as input param and will return a transaction hash
    // which after confirmation will update state variables
    var txHash = myContractInstance.store(hash,{from:account,gas:100000 })
    // After tx has been confirmed, we can retreive the hash stored against a address
    var str = myContractInstance.getStoredHash.call({from:account})
    console.log(str == hash) // return true

Truffle Framework to Compile,Deploy and Interact with Smart Contract

Truffle is a popular development framework for Ethereum, with good documentation , tutorials and boilerplate code Truffle Boxes.
We'll install truffle and use it to compile and deploy our contract and then interact with it.

  1. Install truffle

       npm install -g truffle
    
  2. Initialize truffle

    First create a folder or navigate to empty one

       mkdir project
       cd project
    

    execute init command

       truffle init
    

    it will download initial content and will create folders contracts,migrations and test. project(root) folder will also be populated with two config files, truffle.js and truffle-config.js

    In windows environment remove truffle.js and keep only truffle-config.js to avoid naming conflicts

    populate config file with following code(Geth node or Ganache-Cli client should have already been running exposing HTTP-RPC server at 127.0.0.1:8545 ), for more info view configuration options.

       module.exports = {
        networks: {
            development: {
              host: "127.0.0.1",
              port: 8545,
              network_id: "*" // Match any network id
            }
        }
       };
    
  3. Compile contracts with truffle

    Move or create solidity files in contracts folder, where you will see that a file Migrations.sol already exists, this Migrations.sol contract is used by truffle to manage multiple deployments of contracts with versions.

    navigate to contracts folder

      cd contracts
    

    compile contracts

      truffle compile
    

    it will compile all the contracts and creates a folder build/contracts under project(root) folder with corresponding artifacts.

  4. Deploy contracts with truffle

    Under migrations folder create a new file named "2_deploy_contracts.js" with follwing content. for more info view migrations

       var IPFSHashStorage = artifacts.require("./IPFSHashStorage.sol");
    
       module.exports = function(deployer) {
         deployer.deploy(IPFSHashStorage);
       };
    

    navigate to migrations folder

        cd migrations
    

    deploy contracts

        truffle migrate
    

    this will deploy contracts on to blockchain and update corresponding artifacts under build/contracts with deployment status and address.

  5. Interact with contracts using truffle console

        truffle console
    

    this command will show prompt truffle(development)>.
    Following code will store a hash against a address using store function of the contract.

        var hash = 'QmWWQSuPMS6aXCbZKpEjPHPUZN2NjB3YrhJTHsV4X3vb2t'
        var account = web3.eth.accounts[0]
        IPFSHashStorage.deployed().then(function(instance) { 
         return instance.store(str,{from:account})
        }).then(function(result){
         console.log(result);
        })
    

    which can be retrieved by getStoredHash function of contract using following code snippet

        IPFSHashStorage.deployed().then(function(instance) {
         return instance.getStoredHash.call({from:account})
        }).then(function(result){
         console.log(result);
        })
    

With this we come to end of Part 2 of Building a Dapp on Ethereum Blockchain Series. In this article, we wrote a small smart contract in solidity language, then compiled it, first using command line compiler and again using Node.js. With the help of Web3.js we had deployed it on the blockchain and then interacted with it.we saw that Remix IDE a browser based IDE is also a popular way of developing smart contracts. Finally we took a look on truffle framework, used truffle to again compile, deploy and interact with smart contract.
In Part 3 of this series, we will see what is IPFS, how to store/retreive files in IPFS, and then will integrate it with our smart contract.

If you have liked this article, please share it with others.