Day 10: Deploying the first contract using Etherjs, debugging & bug fixing...

Day 10: Deploying the first contract using Etherjs, debugging & bug fixing...

·

5 min read

#MyLearnings #100DaysOfCode

Intro

For starters, I couldn't complete the lecture as I got stuck on the version incompatibility issue, went through the Etherjs docs, worked around with the Ganache Test Chain, updated & refactored the code multiple times, & worked around to at least pass the deployment connection error, now the only thing I'll need to take care of the gas limit error will handle it eventually.

Deploying SimpleStorage contract:

Setting Up Local Environment:

First of all, install VScode, Nodejs & yarn if possible. Add Solidity extension by Nominic Foundation which will help us in compilation & suggestions. If you've gotten some experience with Nodejs, you could some convenient extensions like prettier, JavaScript (ES6) code snippets, and more. Add solcjs("^0.8.7-fixed") & ethers("^5.6.2") dependencies for solidity code compilation & Etherjs setup accordingly with the exact versions for now as the latest ones have a bit different implementations which I am yet to figure out.

SimpleStorage.sol

Now that we've everything set up, we have to create a SimpleStorage.sol file & paste the Remix IDE code we wrote previously in the file,

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    function addPeople(
        string memory _name,
        int256 _favouriteNumber
    ) public virtual {
        people.push(People({name: _name, favouriteNumber: _favouriteNumber}));
    }

    bool isNumber = false;
    address myAddress = 0x1dA522d5B659B8b6Aee98A8110e98302AcaEbE92;
    uint8 number = 8;
    uint256 num = 123324;
    int128 n = 11;
    string name = "the-third-robot";
    bytes32 byteString = "thee";

    // functions/methods in solidity
    function updateValues(uint256 updatedNUm) public {
        num = updatedNUm;
    }

    // view
    function noGasRequired() public view returns (uint256) {
        return num;
    }

    // pure
    function noGas() public pure returns (uint256) {
        return 1 + 1;
    }

    // struct
    struct People {
        string name;
        int256 favouriteNumber;
    }
    // Array
    // People[10] public people; => array of fixed length
    People[] public people;

    // function addPeople( string memory _name ,int256  _favouriteNumber) public{
    //     people.push(People({name: _name, favouriteNumber : _favouriteNumber}));
    // }
    function retrieveName(uint256 index) public view returns (string memory) {
        string memory nameExtracted = people[index].name;
        return nameExtracted;
    }

    // mappings
    mapping(int256 => People) public peopleMap;

    function addPeopleToMap(
        int256 index,
        string memory _name,
        int256 _favNumber
    ) public {
        peopleMap[index] = People(_name, _favNumber);
    }
}

Compiling contracts

Once we do that, it's time for the deployment setup. first things first, we need to compile our solidity code for which we will be running the command in the terminal,

yarn solcjs --bin --abi --include-path node_modules/ --base-path . -o . SimpleStorage.sol

running the same command again & again can be tedious, so we can just create a script in package.json with the key "compile" & just run the command "yarn compile" as follows,

  "scripts": {
    "compile": "yarn solcjs --bin --abi --include-path node_modules/ --base-path . -o . SimpleStorage.sol"
  },

After compilation, there will be two files generated .bin & .abi which are useful in creating the instance of the contract.

Imports necessary

Now is the time we will be using Etherjs to deploy our contract, let's import all the dependencies necessary,

const ethers = require("ethers");
const fs = require("fs")

Establishing connection with chain & creating wallet

Open the Ganache test blockchain & copy the localhost & one of the wallet's private keys on which you would want our contract to be deployed, & paste it into appropriate places in the code below,

    const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:7545");
    const wallet = new ethers.Wallet(
        "0x07c9e3ab66efc28d7d969c5e6daff5fd7e52a993f30aa21706e2b4a3536980ce",
        provider,
    );

In the first line above, we've connected to the blockchain provider, & in the second line, we created a wallet with the private key & the provider.

Create & Deploy the Contract

Now we need the ABI & Binary to create the instance of the contract & we will get them from the .bin & .abi files with the help of the "fs" file handler as follows,

const abi = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.abi", "utf8");
const binary = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.bin", "utf8");

Now let's create the Contract Factory which is an object we create to deploy the contracts, we parse in the abi, bin & wallet i.e. the contract instance data, & the wallet data as well & the Contract Factory takes care of handling all the necessary stuff, we just need to create it & deploy it as follows,

const contractFactory = new ethers.ContractFactory(abi, binary, wallet);
await contractFactory.deploy();

Once done the code/script for contract deployment should look as shown below with the file name deploy.js,

const ethers = require("ethers");
const fs = require("fs")

async function main() {
    console.log(`Run 1`);
    // http://127.0.0.1:7545
    // connecting our script to our local blockchain
    const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:7545");
    // add a private key & the provider to access the blokchain wallet from code
    const wallet = new ethers.Wallet(
        "0x07c9e3ab66efc28d7d969c5e6daff5fd7e52a993f30aa21706e2b4a3536980ce",
        provider,
    );
    // For deploying the smartcontract, we need the ABI & binary of that particular contract i.e. of SimpleStorage.sol
    // when we ran the deploy script, .abi & .bin files got created which contain the ABI & binary for the contract.
    // We will be using the internal fs(file system) library to extract both of them from the files.
    const abi = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.abi", "utf8");
    const binary = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.bin", "utf8");

    const contractFactory = new ethers.ContractFactory(abi, binary, wallet);

    try {
        await contractFactory.deploy();
    } catch (err) {
        console.log(`Err: ${err}`)
    }
    console.log(`Run 5 `);
}

main()
    .then(() => process.exit(0))
    .catch((err) => console.log(err));

Now ensure that the Ganache server is on & running & hit the command below in the project directory,

node deploy.js

Hurrey! We've successfully deployed our contract on a local test blockchain. You might face some issues with the latest versions & am yet to debug them but till then you can use the mentioned versions to understand the concepts & move ahead with the learnings alongside, that's what am thinking of doing too... cause there are more tools to come & once I get to know what's necessary & what's just okay to know, I could focus on them accordingly, kind of a new thing am trying out.

Outro

The learnings are becoming more exciting day by day, getting more challenging concepts to learn, the only important & crucial thing is to be consistent throughout the process. So far these are some of the learnings that I can share with you all, I've tried to put everything as per my understanding & there's a chance that I might've mistaken somewhere, so, feel free to correct me on anything in the comments.

Wrapping up my Day-10 of #100DaysOfCode, will catch up again tomorrow, till then, it's a farewell.