Solidity Smart Contract Development - Mastering ethers.js

Author: pseudoyu | 1070 words, 3 minutes | comments | 2022-06-08 | Category: Develop

blockchain, ethereum, ethers.js, javascript, smart contract, solidity, web3

Translations: ZH, DE

《後來的我們 - 五月天》

Preface

In the previous article “Solidity Smart Contract Development - Basics”, we learned the basic syntax of Solidity and understood that we can debug using frameworks like Brownie and HardHat. In another article “Solidity Smart Contract Development - Mastering Web3.py”, we also interacted directly with our local Ganache node using Web3.py.

Originally, because I was more familiar with Python, I planned to use the Brownie framework for subsequent development. However, after some research, I found that the industry predominantly uses the HardHat framework, which also has more extensions. Additionally, the Solidity tutorial I’m following has updated to a Javascript version, so I decided to learn it.

To better understand the principles and lay a good foundation for our subsequent use of the framework, this time we will use ethers.js to interact with our Rinkeby test network deployed on the Alchemy platform. We will implement basic contract compilation, deployment to the Rinkeby network, and interaction with the contract.

You can click here to access the code repository for this test demo.

ethers.js

ethers.js is an open-source library for Javascript that can interact with the Ethereum network. Its GitHub address is ethers.io/ethers.js, and you can visit its official documentation for usage.

Installation

We can install ethers.js using yarn, as follows:

yarn add ethers

yarn_add_ethers

Usage

Import the library using require to use it

const ethers = require('ethers');

Solidity Contract Compilation

Contract Source Code

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

contract SimpleStorage {
    uint256 favoriteNumber;
    bool favoriteBool;

    struct People {
        uint256 favoriteNumber;
        string name;
    }

    People public person = People({favoriteNumber: 2, name: "Arthur"});

    People[] public people;

    mapping(string => uint256) public nameToFavoriteNumber;

    function store(uint256 _favoriteNumber) public returns (uint256) {
        favoriteNumber = _favoriteNumber;
        return favoriteNumber;
    }

    function retrieve() public view returns (uint256) {
        return favoriteNumber;
    }

    function addPerson(string memory _name, uint256 _favoriteNumber) public {
        people.push(People({favoriteNumber: _favoriteNumber, name: _name}));
        nameToFavoriteNumber[_name] = _favoriteNumber;
    }
}

This is a simple storage contract that uses a People struct object to store a person’s name and their favorite number, uses an array to store information for multiple people, and provides methods for adding and searching.

Reading the Contract Source File

After completing the Solidity contract writing and syntax checking through VSCode or other editors, we need to compile the contract into abi file and bytecode.

We can install the solc command-line tool through yarn for editing, and we can choose the corresponding version. The command is as follows:

After installation, we can use the solcjs command for compilation. The command is as follows:

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

Since compiling contracts is a high-frequency operation, we can configure the compile script command in package.json as follows:

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

After that, you only need to execute yarn compile to generate the contract compilation files.

Obtaining Compilation Results

After compilation, abi and bytecode files will be generated, with .bin and .abi as suffixes respectively.

Obtaining bytecode and abi

The deployment and interaction of Solidity contracts require two parts: bytecode and abi. We can write them into corresponding variables for subsequent operations through the following code.

const fs = require('fs-extra');

const abi = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.abi", "utf-8");
const binary = fs.readFileSync("./SimpleStorage_sol_SimpleStorage.bin", "utf-8");

Creating a Rinkeby Test Network Environment (Alchemy)

Debugging smart contracts requires deploying the contract to an actual chain. We choose to deploy to the Rinkeby test network on the Alchemy platform for subsequent debugging and development.

Alchemy Platform

First, we visit the Alchemy official website, register and log in, and we will see its Dashboard, which displays all created applications.

alchemy_dashboard

After installation, select Create App to quickly create a Rinkeby test network node.

alchemy_create_app

After creation, click View Details to see the detailed information of the App we just created. Click View Key in the upper right corner to query our node information. We need to record the HTTP URL for subsequent connection use.

alchemy_app_detail

Creating a Rinkeby Test Account (MetaMask)

MetaMask

After creating the Rinkeby test network environment, we need to create an account through MetaMask, get some test tokens, and record the account’s private key for later use.

metamask_private_key

Obtaining Test Tokens

After creating an account, we need some test tokens for subsequent development and debugging. We can obtain them through the following URLs:

Connecting to Test Node and Wallet

Connecting to Node

ethers.js provides a library that can easily connect to our test node, where process.env.ALCHEMY_RPC_URL is the HTTP URL of the App we created on the Alchemy platform:

const ethers = require('ethers');

const provider = new ethers.providers.JsonRpcProvider(process.env.ALCHEMY_RPC_URL);

Connecting to Wallet

ethers.js also provides a method to connect to our test wallet, where process.env.RINKEBY_PRIVATE_KEY is the private key we copied from MetaMask.

const ethers = require('ethers');

const wallet = new ethers.Wallet(
	process.env.RINKEBY_PRIVATE_KEY,
	provider
);

Solidity Contract Deployment

Creating Contract

We can create a contract through the ethers.js library.

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

Deploying Contract

Below we will introduce how to deploy a contract through the ethers.js library, where the ABI and BIN files of the SimpleStorage contract have been read in the code above.

Creating Contract

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

Deploying Contract

const contract = await contractFactory.deploy();
await contract.deployTransaction.wait(1);

Interacting with Contract

We can also interact with the contract through ethers.js.

retrieve()

const currentFavoriteNumber = await contract.retrieve();

store()

const transactionResponse = await contract.store("7")
const transactionReceipt = await transactionResponse.wait(1);

Constructing Transaction from Raw Data

In addition to directly calling methods to deploy contracts, we can also construct transactions ourselves.

Constructing Transaction

const nonce = await wallet.getTransactionCount();
const tx = {
	nonce: nonce,
	gasPrice: 20000000000,
	gasLimit: 1000000,
	to: null,
	value: 0,
	data: "0x" + binary,
	chainId: 1337,
};

Signing Transaction

const signedTx = await wallet.signTransaction(tx);

Sending Transaction

const sentTxResponse = await wallet.sendTransaction(tx);
await sentTxResponse.wait(1);

Conclusion

The above are the steps for interacting with the Rinkeby test network of Alchemy through the ethers.js library. In actual production project development, we generally do not directly use libraries like ethers.js, but instead use further encapsulated frameworks like Brownie and HardHat. However, understanding how to use libraries like Web3.py or ethers.js is also very important. I will further explain the use of the HardHat framework in the future.

References

  1. Solidity Smart Contract Development - Basics
  2. Solidity Smart Contract Development - Mastering Web3.py
  3. Solidity, Blockchain, and Smart Contract - Javascript Version
  4. ethers.js Project Repository
  5. ethers.js Official Documentation
  6. Alchemy Official Website

Related Posts

2023-09-13
Weekly Review #46 - Farewell to Long Hair, Weekly Review's Original Intention, and Contract Development
2023-04-30
Weekly Review #38 - Foundry Contract Testing, Logseq Task Management, and Surge Ponte Remote Development
2022-07-01
Implementing Two-Phase Commit in Solidity Smart Contracts Using State Locks
2022-06-09
Solidity Smart Contract Development - Using the Hardhat Framework
2022-05-30
Solidity Smart Contract Development - Mastering Web3.py
pseudoyu

Author

pseudoyu

Backend & Smart Contract Developer, MSc Graduate in ECIC(Electronic Commerce and Internet Computing) @ The University of Hong Kong (HKU). Love to learn and build things. Follow me on GitHub


Comments