5 min read

🧰 Web3 [Serie Part 3/10] - Create A Contract Instance

🧰 Web3 [Serie Part 3/10] - Create A Contract Instance

Introduction

In this chapter, we will learn how to create an instance of our Smart Contract. This part is required to interact with our contract.

What is a Contract Instance?

The Contract Instance is an object produced by the library Web3 creating a contract instance to interact with our Smart Contract.

Web3 Instances Levels Overview
Web3 Instances Levels Overview

Why don't we interact directly with the Smart Contract?

Well, each Smart Contracts are different and have their own functions, and addresses. So, we need to teach Web3 how to 'speak' with our Smart Contract.

To create our Contract Instance, Web3 is requiring 2 parameters:

Two parameters required by Web3 to create a Contract Instance: the Contract Address, and the Contract ABI
Two parameters required by Web3 to create a Contract Instance: the Contract Address, and the Contract ABI

Contract Address

A Contract Address is the address of the place where our Smart Contract is stored on the Ethereum Blockchain. It will allow us to send, or withdraw funds for instance.

Contract ABI

ABI stands for β€˜Application Binary Interface’.

The Contract ABI is a JSON document describing all the functions, and variables used in the Smart Contract, callable from outside the Blockchain.

The ABI is generated by compiling/building our Smart Contract written in Solidity.

Smart Contract Development & Building

In this Serie, we won't cover the Solidity development part. Thus, we will use an already developed simple Smart Contract code. Β Nevertheless, we will go the 3 steps of deploying a Smart Contract.


Step 1 - Code the Smart Contract

First, we are going to generate a basic development framework thanks to Truffle (installed in the part 1 of this serie). In our main directory, we run the following command:

truffle init
Initialize with Truffle

As a result you should have the following directory tree:

β”œβ”€β”€ contracts
β”‚Β Β  └── Migrations.sol
β”œβ”€β”€ index.js
β”œβ”€β”€ migrations
β”‚Β Β  └── 1_initial_migration.js
β”œβ”€β”€ node_modules
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
β”œβ”€β”€ test
└── truffle-config.js
Directory Tree post 'truffle init' command (node_modules have been simplified for readability)

In the Contracts directory, create a new file 'MyContract.sol' (.sol is standing for Solidity language).

To keep things simple, we will be using the Smart Contract used as example in Solidity documentation. We will just change a few things.

Initial code from Solidity documentation

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract SimpleStorage {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public view returns (uint) {
        return storedData;
    }
}
Smart Contract initial code from Solidity Documentation (before our small changes)

Here is the final code we will be using. Comments are following.

pragma solidity >=0.4.16 <0.9.0;

contract MyContract {
    uint data;

    function set(uint x) public {
        data = x;
    }

    function get() public view returns (uint) {
        return data;
    }
}
MyContract.sol
  • First we define the Solidity version we are using.
  • Then, we define a new contract, called MyContract.
  • Next, we define an 'uint' (standing for Unsigned Integer) called data.
  • The two functions below are respectively a setter function, i.e. replacing data value by x, and a getter function, i.e. returning data value.
  • The public keywords mean that we can access these functions from outside the Smart Contract, thanks to Web3. Without that keyword, we could not access the variable or the function.

Step 2 - Code the Migration File

Now, we need to script a migration file. This script is telling Truffle how to migrate our Smart Contract to the blockchain.

In the migration directory, we create a new file named 2_contract_deploy.js (2 is important).

We add the following script in the migration file:

const MyContract = artifacts.require('MyContract');

module.exports = function(deployer){
    deployer.deploy(MyContract);
}
2_contract_deploy.js

Step 3 - Compile & Migrate the Smart Contract

Now that we scripted our Smart Contract, and wrote our Migration file, we can launch the building process, and the migration.

In our main directory, we run the following command:

truffle migrate --reset
Truffle Migration Command

Comment

  • the reset tag stands for resetting potential previous migration. In this first case, this is not required, but if you encounter error in the compilation, you would restart your truffle migration adding the --reset to start from scratch.

We will see the following results:

Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/MyContract.sol
> Artifacts written to /Users/henririon/Documents/Tutorials/web3-tutorial/build/contracts
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



Starting migrations...
======================
> Network name:    'ganache'
> Network id:      5777
> Block gas limit: 6721975 (0x6691b7)


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x9907bdca7b17841fac28db587cf3b674481348e9bb730fb1e6b6722d1d09bc31
   > Blocks: 0            Seconds: 0
   > contract address:    0x3aa84f14eC87a764a4950AA2A1C1F4849bCC60d1
   > block number:        1
   > block timestamp:     1630419782
   > account:             0x8ba7dDC383130c3D5c3afC76AD3f3343571246E8
   > balance:             99.99616114
   > gas used:            191943 (0x2edc7)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00383886 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00383886 ETH


2_contract_deploy.js
====================

   Deploying 'MyContract'
   ----------------------
   > transaction hash:    0xd24cdd7f0a11fe02a747fa3bc701a7de3a893c2995da145cbe360c57a93b47c4
   > Blocks: 0            Seconds: 0
   > contract address:    0xdfC6BF4043dE741A57f57d1f065e365849f5af7C
   > block number:        3
   > block timestamp:     1630419782
   > account:             0x8ba7dDC383130c3D5c3afC76AD3f3343571246E8
   > balance:             99.9933906
   > gas used:            96189 (0x177bd)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00192378 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00192378 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.00576264 ETH

A few comments about this results:

  • First, as indicated, Truffle compile our Smart Contract.
  • Next, it starts the migration. First, the initial migration, and second our '2_contract_deploy.js'.
  • For each migration, we got the transaction hash parameter informing us about the block number, the contract address, the total cost, etc.

Our Smart Contract has been successfully compiled, and migrated to our local blockchain, Ganache.

If we check our main directory, we should see a new directory called 'build'. Inside, we will find a file called MyContract.json, which is our Contract ABI.

VS Code Directory Overview - Focusing on Build directory, and the Contract ABI
VS Code Directory Overview - Focusing on Build directory, and the Contract ABI

As explained earlier, to create our Smart Contract Instance, Web3 is requiring 2 parameters: the Contract Address, and the Contract ABI. We now have both, and we can start coding.

Create our Smart Contract Instance

Now, that we generate our Smart Contract ABI, we can actually retrieve both parameters we need inside the generated MyContract.json file.

If we open the ABI Json file, we can see at the end of the file, the following piece of code:

[...]

"networks": {
    "5777": {
      "events": {},
      "links": {},
      "address": "0xdfC6BF4043dE741A57f57d1f065e365849f5af7C",
      "transactionHash": "0xd24cdd7f0a11fe02a747fa3bc701a7de3a893c2995da145cbe360c57a93b47c4"
    }
    
[...]
MyContract.json = MyContract ABI

The mentioned address is our Smart Contract address deployed in our local Blockchain, Ganache.

Now, we have everything to create our Smart Contract instance.

Here is the complete code. Comments are following.

const Web3 = require('web3');
const MyContract = require('./build/contracts/MyContract.json');

const main = async() => {
    const web3 = new Web3('http://127.0.0.1:7545');

    const id = await web3.eth.net.getId();
    const contract = new web3.eth.Contract(
        MyContract.abi,
        MyContract.networks[id].address
    );

    console.log(contract);
}

main();
index.js
  • We import MyContract.json, our Contract ABI as MyContract.
  • Then, we use the web3.eth.net.getId() methods to retrieve the current Network ID. It will help us finding our Smart Contract address.
  • Next we create our Contract Instance by giving the two required parameters: the Contract ABI, and the Contract address.
  • To check if everything is fine we console.log our contract instance.

πŸŽ‰ πŸ₯³ πŸ‘―β€β™‚οΈ 🎈 Congratulations! We successfully instantiate our first Smart Contract. Let's move on and interact with our Smart Contract now.