使用truffle部署合约练习ethers库,对比web3js与ethers的使用

前言

使用 truffle部署合约,并练习ethers库。 之前一直是使用web3js,今天看到一个源码使用了ethers,看了之后感觉比web3js方便很多。

web3js 与 ethers对比

连接到以太坊

// web3 
var Web3 = require('web3'); var web3 = new Web3('http://localhost:8545'); 
// ethers 
var ethers = require('ethers'); const url = "http://127.0.0.1:8545"; const provider = new ethers.providers.JsonRpcProvider(url);

签名对象

在ethers中,签名者是以太坊账户的抽象。它可用于对消息和交易进行签名,并将签名的交易发送到以太坊网络。 在 web3 中,可以使用一个帐户来签署消息和交易。

// web3 
const account = web3.eth.accounts.create(); 
// ethers (create random new account) 
const signer = ethers.Wallet.createRandom(); 
// ethers (connect to JSON-RPC accounts) 
const signer = provider.getSigner();

使用私钥生成账号对象生成调用的方法不同,不过使用上大同小异。

// web3
const signer = web3.eth.accounts.privateKeyToAccount(private_key)
//ethers
const signer = new ethers.Wallet(private_key);

账号签名

// web3 (using a private key) 
signature = web3.eth.accounts.sign('Some data', privateKey) 
// ethers 
signature = await signer.signMessage('Some data')

合约调用

只读方法

// web3js
const contract = new this.web3.eth.Contract(abi, contract_address)
const token_blance = await contract.methods.balanceOf(wallet_address).call()
const blance = this.web3.utils.fromWei(token_blance, 'ether')

// ethers
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);
const res = await daiContract.balanceOf(myaddress).toString()

上述方法中使用web3js需要去下载相应的ABI,比如你可以去etherscan下载,而在ethers中,你可以直接传入方法生成daiAbi

const daiAbi = [
  // Some details about the token
  "function name() view returns (string)",
  "function symbol() view returns (string)",

  // Get the account balance
  "function balanceOf(address) view returns (uint)",

  // Send some of your tokens to someone else
  "function transfer(address to, uint amount)",

  // An event triggered whenever anyone transfers to someone else
  "event Transfer(address indexed from, address indexed to, uint amount)"
];
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);

实践目标

1.使用truffle部署一个合约 2.使用truffle console 进行交互 3.使用ethers进行合约交互练习

安装环境

yarn global add truffle
yarn install ethers
# 或者
npm install -g truffle 
npm install ethers

编写合约

实现一个最简单的合约

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.0;

/**
 * @title Storage
 * @dev Store & retrieve value in a variable
 */
contract Storage {

    uint256 number;

    /**
     * @dev Store value in variable
     * @param num value to store
     */
    function store(uint256 num) public {
        number = num;
    }

    /**
     * @dev Return value 
     * @return value of 'number'
     */
    function retrieve() public view returns (uint256){
        return number;
    }
}
# 编译
truffle compile
# 部署
truffle migrate 

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


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

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x67c58fd2401c5bc506591f30b9566be6e8226c8b09a8125a511224cfa5029f7f
   > Blocks: 0            Seconds: 0
   > contract address:    0x25A6E016CB92D46fe8cE3f74D4F93b6439F6Cc89
   > block number:        14820726
   > block timestamp:     1653184639
   > account:             0x4BC9E31c338C402Aa2590E7008a879B5a66A8568
   > balance:             99.995114
   > gas used:            244300 (0x3ba4c)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.004886 ETH


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


2_deploy_contracts.js
=====================

   Replacing 'Storage'
   -------------------
   > transaction hash:    0x45ae44d9c9730485b0208dbbb0d1116398f9d562931024fc9757e5b603160cc1
   > Blocks: 0            Seconds: 0
   > contract address:    0xFe87778700B9dda2B5FD5fb7895120C33a331E69
   > block number:        14820728
   > block timestamp:     1653184640
   > account:             0x4BC9E31c338C402Aa2590E7008a879B5a66A8568
   > balance:             99.9918876
   > gas used:            118807 (0x1d017)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00237614 ETH


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


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

部署完成之后,我们可以使用 truffle console 进行交互

let ins = await Storage.deployed()
await ins.store(7)
let n2 = await ins.retrieve()
n2
# BN { negative: 0, words: [ 7, <1 empty item> ], length: 1, red: null }

所以上述合约就只有2个方法 一个read方法:retrieve 一个write方法:store 所以通过 truffle 可以直接跟他进行交互 代码实现的功能:调用storage合约,将number修改为10,并且读取一次number的值。 ethers可以直接根据方法名生成abi,比web3js方便很多。

const { ethers } = require("ethers");

const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545");


(async () => {
  const num = await provider.getBlockNumber();
  console.log(num);
  const singer = new ethers.Wallet(
    "private_key"
  );
  const myaddress = singer.address;
  console.log(myaddress);
  const signature = await singer.signMessage("some data");
  console.log(signature);
  const contractAddress = "0xFe87778700B9dda2B5FD5fb7895120C33a331E69";

  const storageAbi = [
    "function retrieve() view returns (uint256)",

    "function store(uint256 num)",
  ];

  // The Contract object
  const storageContract = new ethers.Contract(
    contractAddress,
    storageAbi,
    provider.getSigner()
  );
  const res = await storageContract.store(10);
  console.log(res);

  const res2 = await storageContract.retrieve();
  console.log(res2.toString());
})();

综上所述,对比web3js,ethers封装了更方便的api接口,能简化一些调用流程。

参考

Ethers Getting Started