ethers.js读写合约里的状态变量

Posted sanqima

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ethers.js读写合约里的状态变量相关的知识,希望对你有一定的参考价值。

    在ethers.js里,对合约状态变量的访问有2种方式:只读方式和读写方式。当访问合约里的状态变量时,需要知道该合约的地址、abi、provider(或signer),只读方式,只能读取状态变量;而读写方式,既可以读取状态变量,还可以修改状态变量。格式如下:

//1) 只读方式
contract = new ethers.Contract(contAddress,contAbi,provider)

//2) 读写方式
contract = new ethers.Contract(contAddress,contAbi,signer)
  • Only Read 只读方式
    只读方式,不消耗gas,需要提供provider,只能读取状态变量,无法修改状态变量。

  • Read and Write 读写方式
    读写方式,消耗gas,需要提供signer,既可以读取状态变量,也可以修改状态变量。

    这里以hardhat读取和修改greeter.sol合约里的状态变量greeting为例,进行说明。

1、创建工程tokenhat

1.1 创建文件夹并初始化

mkdir tokenhat
cd tokenhat
npm init -y

1.2 修改package.json文件

    修改好的package.json文件如下:

{
  "name": "tokenhat",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \\"Error: no test specified\\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@nomiclabs/hardhat-ethers": "^2.0.2",
    "@nomiclabs/hardhat-waffle": "^2.0.1",
    "chai": "^4.3.4",
    "ethereum-waffle": "^3.4.0",
    "ethers": "^5.4.7",
    "hardhat": "^2.6.5",
    "ethereumjs-abi": "^0.6.8"
  }
}

1.3 安装依赖包并初始化hardhat

npm install 
npx hardhat
## 选中Create a sample project,然后,一路按Enter键即可。

1.4 修改solidity的版本

    在hardhat.config.js文件里,将solidity的版本修改为0.5.12,如下:

require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.5.12", //修改此处的版本
};

2、创建和部署智能合约

    a) 在tokenhat/contracts目录里,修改greeter.sol合约,具体如下:
    //greeter.sol

//SPDX-License-Identifier: Unlicense
// pragma solidity ^0.8.0;
pragma solidity ^0.5.0;

import "hardhat/console.sol";

contract Greeter {
    string private greeting;

    constructor(string memory _greeting) public {
        console.log("Deploying a Greeter with greeting:", _greeting);
        greeting = _greeting;
    }

    function greet() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _greeting) public {
        console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
        greeting = _greeting;
    }
}

    b) 新建部署脚本
    在tokenhat/script目录下,新建一个部署脚本:1_deploy_greeter.js
    // scripts/1_deploy_greeter.js

const hre = require("hardhat");

async function main() {
  // We get the contract to deploy
  const Greeter = await hre.ethers.getContractFactory("Greeter");
  const greeter = await Greeter.deploy("Hello, Hardhat!");

  await greeter.deployed();

  console.log("Greeter deployed to:", greeter.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

    c) 部署智能合约到本地

// 启动hardhat本地私有链(127.0.0.1:8545)
npx hardhat node

// 编译智能合约
npx hardhat compile

// 部署智能合约到localhost
npx hardhat run scripts\\1_deploy_greeter.js --network localhost

3、读取和修改状态变量

3.1 读取状态变量

    在tokenhat/test目录下,新建一个脚本: 4_onlyRead.js,用于读取greeting的值,内容如下:
    //4_onlyRead.js

const { expect } = require("chai");
const { ethers } = require("hardhat");
const fs = require("fs");

describe("greeter test",function() {

    before(async function() {
        this.provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
        // this.signer1 = this.provider.getSigner();
        
        this.contJson = fs.readFileSync("./myabi/greeter_abi.json") //abi文件
        this.contAbi = JSON.parse(this.contJson) //转换为json个数
        this.contAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3" //合约的地址
        this.contract = new ethers.Contract(this.contAddress,this.contAbi,this.provider)

    })
   
    //2)开始测试
    context("connect smart contract",async function() {      
        it("getGreete",async function() {
            expect(await this.contract.greet()).to.equal("Hello world");
        })
    });

});


3.2 修改状态变量

    在tokenhat/test目录下,新建一个脚本: 5_writeRead.js,内容如下:
    //5_writeRead.js

const { expect } = require("chai");
const { ethers } = require("hardhat");
const fs = require("fs");

describe("greeter test",function() {

    before(async function() {
        this.provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
        this.signer1 = this.provider.getSigner();
        
        // this.contJson = fs.readFileSync("./myabi/greeter_abi.json") //abi文件
        // this.contAbi = JSON.parse(this.contJson)            //转化为json个数

        this.contFile = fs.readFileSync("./artifacts/contracts/Greeter.sol/Greeter.json") 
        this.contAbi = JSON.parse(this.contFile).abi
        this.contAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3" //合约的地址
        this.contract = new ethers.Contract(this.contAddress,this.contAbi,this.signer1)

    })

   
    //1)开始测试
    context("connect smart contract",async function() {       
        it("setGreete",async function() {
            const setGreetingTx = await this.contract.setGreeting("Hello world");

            // wait until the transaction is mined
            await setGreetingTx.wait();
            expect(await this.contract.greet()).to.equal("Hello world");
        })

        it("getGreete",async function() {
            expect(await this.contract.greet()).to.equal("Hello world");
        })
    });

});

3.3 进行测试

## 进入工程目录
cd tokenhat

## 修改状态变量
npx hardhat test test\\5_writeRead.js

## 读取状态变量
npx hardhat test test\\4_onlyRead.js

    效果如下:

图(1) 访问合约里的状态变量

参考文献

[1] hardhat以太坊全栈开发
[2] 使用Next.js和Next-Auth-js在Ethreum开发带有社区认证的Dapp

以上是关于ethers.js读写合约里的状态变量的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ethers.js 向智能合约发送静态调用

Ethers.js,向智能合约汇款(接收功能)

使用ethers.js部署Solidity智能合约

使用ethers.js直接读取智能合约中插槽内容

我如何将 eth 值发送到在 ethers.js 中支付的特定智能合约功能?

无法解码交易数据