Waffle使用初体验

2023-11-18

一、什么是Waffle

Waffle是什么呢?我们直接看其文档上的介绍:

Waffle is a library for writing and testing smart contracts. Sweeter, simpler and faster than Truffle. Works with ethers-js.

大致意思为,它是一个编写和测试(以太坊上)智能合约的库,比Truffle更加好用,简单和快速,它使用了ethers-js

注:(ethers-js 是一个非常棒的以太坊js框架,个人觉得甚至好于web3.js)。

介绍完之后我们根据其官方文档进行初次使用。

二、安装

2.1、安装yarn

yarn安装链接为:https://yarn.bootcss.com/docs/install/#mac-stable,注意选择相应的操作系统。

2.2、新建一个yarn工程

打开一个终端,运行下面的命令:

mkdir waffle_test
cd waffle_test/
yarn init

然后一路回车,会出现如下提示:

success Saved package.json
✨  Done in 25.49s.

这说明我们的yarn工程已经建立好了。我们接着运行code .来使用VS Code打开该工程(如果没有code命令就手动打开VS Code)。

在VS Code里我们可以看到本工程仅有一个package.json,接下来我们一步一步充实该工程。

2.3、安装waffle及一些依赖

下面我们按照其官方文档介绍的流程进行操作:

2.3.1、安装ethereum-waffle

打开VS Code的终端菜单,新建一个终端,在其中运行:

yarn add --dev ethereum-waffle

2.3.2、安装智能合约依赖

yarn add @openzeppelin/contracts -D

可以看到,我们安装了openzeppelin提供的一些标准模板合约。

三、编写智能合约并编译

3.1、编写一个测试合约

在项目根目录下新建src目录,并在src目录下建立BasicToken.sol,内容如下:

pragma solidity ^0.6.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

// Example class - a mock class using delivering from ERC20
contract BasicToken is ERC20 {
  constructor(uint256 initialBalance) ERC20("Basic", "BSC") public {
      _mint(msg.sender, initialBalance);
  }
}

可以看到,这是一个简单的测试用的ERC20合约,在构造器里初始化了发行总量。

3.2、编译合约

3.2.1、编辑package.json,添加如下内容。

{
  "scripts": {
    "build": "waffle"
  }
}

注意:官方文档提到,当waffle版本不同时,它的内容也不同。waffle 3.0.0以上(当前版本是3.2.0)就是这样设置;如果是2.5.0版本,则为:

{
  "scripts": {
    "build": "waffle waffle.json"
  }
}

我们当前是3.0.0以上版本,所以不需要手动在后面加waffle.json,默认值就是它。

3.2.2、创建waffle.json

在项目根目录下创建waffle.json,内容为:

{
  "compilerType": "solcjs",
  "compilerVersion": "0.6.2",
  "sourceDirectory": "./src",
  "outputDirectory": "./build"
}

它定义了一些最基本的配置,很容易看明白。但是这里按照官方文档实际操作有些问题,我们接下来会讲。

3.2.3、编译

运行yarn build

会提示获取不到0.6.2版本的编译器,怎么办呢?我们可以参考Uniswap项目,修改上面的waffle.json,将compilerVersion的值改为:"./node_modules/solc",官方文档有介绍compilerVersion的几种格式。

所以修改后的waffle.json为:

{
    "compilerType": "solcjs",
    "compilerVersion": "./node_modules/solc",
    "sourceDirectory": "./src",
    "outputDirectory": "./build"
}

再次运行yarn build,则会有Done in 5.93s.类似的提示,代表我们合约已经编译好了。这时可以看到,项目根目录下多了build目录,里面有多个json文件,这就是编译后合约对应的json文件。

四、编写测试

4.1、安装测试库

Waffle使用MochaChai进行测试,所以必须先安装它们:

yarn add --dev mocha chai

4.2、编写测试文件

安装完成之后,在项目根目录下新建test目录,然后在该目录下新建BasicToken.test.ts,内容如下:

import {expect, use} from 'chai';
import {Contract} from 'ethers';
import {deployContract, MockProvider, solidity} from 'ethereum-waffle';
import BasicToken from '../build/BasicToken.json';

use(solidity);

describe('BasicToken', () => {
  const [wallet, walletTo] = new MockProvider().getWallets();
  let token: Contract;

  beforeEach(async () => {
    token = await deployContract(wallet, BasicToken, [1000]);
  });

  it('Assigns initial balance', async () => {
    expect(await token.balanceOf(wallet.address)).to.equal(1000);
  });

  it('Transfer adds amount to destination account', async () => {
    await token.transfer(walletTo.address, 7);
    expect(await token.balanceOf(walletTo.address)).to.equal(7);
  });

  it('Transfer emits event', async () => {
    await expect(token.transfer(walletTo.address, 7))
      .to.emit(token, 'Transfer')
      .withArgs(wallet.address, walletTo.address, 7);
  });

  it('Can not transfer above the amount', async () => {
    await expect(token.transfer(walletTo.address, 1007)).to.be.reverted;
  });

  it('Can not transfer from empty account', async () => {
    const tokenFromOtherWallet = token.connect(walletTo);
    await expect(tokenFromOtherWallet.transfer(wallet.address, 1))
      .to.be.reverted;
  });

  it('Calls totalSupply on BasicToken contract', async () => {
    await token.totalSupply();
    expect('totalSupply').to.be.calledOnContract(token);
  });

  it('Calls balanceOf with sender address on BasicToken contract', async () => {
    await token.balanceOf(wallet.address);
    expect('balanceOf').to.be.calledOnContractWith(token, [wallet.address]);
  });
});

本测试文件由官方文档提供,具体测试内容很简单,有兴趣的读者可以自己看一下。这里因为主要是介绍waffle的使用,所以略过测试内容及测试文件的编写。

4.3、运行测试

根据其官方文档,运行测试前我们需要更新package.json,使之包括如下内容:

{
  "scripts": {
    "build": "waffle",
    "test": "export NODE_ENV=test && mocha",
  }
}

这里其实就是加上test脚本的运行命令。

然后运行yarn test

然而,会报出Error: No test files found: "test",这是为什么呢?严格按照官方文档操作怎么就报错了呢,笔者在这里也坑了许久。多方查阅及和waffle本身的示例对照之后发现,是少了一个Mocha的配置文件。因为我们安装的是最新的Mocha,所以这里需要修改一下package.json,添加一个mocha属性并设置,使之包含如下内容:

{
  "mocha":{
    "extension": ["ts"],
    "spec": "./test/**/*.test.ts",
    "require": "ts-node/register",
    "timeout": 12000
  },
}

然后再次运行yarn test,会报错说找不到一些依赖包,这个我们下一步来解决。

注意:这里需要说明的是,mocha配置文件的设置方法有好几种(查看mocha对应的官方文档)。Waffle在github仓库中的示例使用的方法不是在package里设置,而是在test目录下新建了一个mocha.opts,其内容为:

-r ts-node/register/transpile-only
--timeout 50000
--no-warnings
test/**/*.test.{js,ts}

然而经过测试,当前mocha的版本为8.2.1(这个可以从package.json中查看)时,它不会读取mocha.opts,所以就算test目录下有此文件,也仍然会出现Error: No test files found: "test"的问题。

解决该问题的办法有两种:

  1. mocha的版本回退,比如设置为"^7.1.2",然后再运行yarn来安装该版本的mocha,这样就可以读取配置文件了。
  2. 正如前面提到的,在package.json里(或者别处,参考mocha文档)进行设置而不是使用test/mocha.opts

4.4、安装其它依赖

接着刚才的操作,请确认是在package.json里进行mocha设置而不是使用mocha.opts

再次运行yarn test会提示ERROR: Error: Cannot find module 'ts-node/register'。这是一些依赖库未安装,我们来依次安装:

yarn add ts-node -D
yarn add typescript -D
yarn add @types/chai -D
yarn add @types/mocha -D

4.5、tsconfig.json

安装完成之后我们再次运行yarn test

然而,又又又报错了,这次提示为:error TS2732: Cannot find module '../build/BasicToken.json',意思为找不到目录下相应的json文件。这里通过比对其示例,发现少了一个tsconfig.json配置文件。

我们把它加上去,在项目根目录下新建tsconfig.json,内容如下(该内容直接复制的官方示例):

{
  "compilerOptions": {
    "declaration": true,
    "esModuleInterop": true,
    "lib": [
      "ES2018"
    ],
    "module": "CommonJS",
    "moduleResolution": "node",
    "outDir": "dist",
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true,
    "target": "ES2018"
  }
}

再次运行yarn test,会有类似如下输出:

yarn run v1.22.5
$ export NODE_ENV=test && mocha


  BasicToken
    ✓ Assigns initial balance
    ✓ Transfer adds amount to destination account (120ms)
    ✓ Transfer emits event (97ms)
    ✓ Can not transfer above the amount
    ✓ Can not transfer from empty account
    ✓ Calls totalSupply on BasicToken contract
    ✓ Calls balanceOf with sender address on BasicToken contract


  7 passing (2s)

✨  Done in 8.88s.

可以看到,我们的测试成功了。

五、完整package.json

这里放出完整package.json,方便大家对照一下。

{
  "name": "waffle_test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "@openzeppelin/contracts": "^3.2.0",
    "@types/chai": "^4.2.14",
    "@types/mocha": "^8.0.4",
    "chai": "^4.2.0",
    "ethereum-waffle": "^3.2.0",
    "mocha": "^8.2.1",
    "ts-node": "^9.0.0",
    "typescript": "^4.0.5"
  },
  "mocha":{
    "extension": ["ts"],
    "spec": "./test/**/*.test.ts",
    "require": "ts-node/register",
    "timeout": 12000
  },  
  "scripts": {
    "build": "waffle",
    "test": "export NODE_ENV=test && mocha"
  }
}

六、总结

总结一下,Waffle使用还是挺简单的,但对照其官方文档操作会出现一些坑,也花了一些时间来解决。主要是因为官方文档介绍的流程是有一定的前提条件的,不是从零开始详细介绍其操作过程。另外软件版本的更新也引起了一些问题。

欢迎大家留言指正错误或者提出改进意见。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Waffle使用初体验 的相关文章

随机推荐

  • webpack中引用图片出现Module parse failed: Unexpected character '�' (1:0) You may need an appropriate loader

    1 查看url loader和file loader有没有安装好 如果没有 重新安装 file loader安装指令 npm install save dev file loader url loader安装指令 npm install u
  • UE4 VR WidgetInteraction 局域网设定

    无论用什么 我们要先确定是什么 鲁迅 下面是关于WidgetInteraction的官方定义 控件交互组件执行光线投射 确定它是否命中世界场景中的控件组件 如命中 可设置规则确定与其交互的方式 交互通过模拟定义的按键来执行 例如一个按钮可通
  • Python语言基础—一文看懂Python异常

    系列文章目录 Python语言基础 注释的作用及分类 Python语言基础 常用运算符总结 Python语言基础 定义变量与数据类型 Python语言基础 if判断和循环总结 Python语言基础 理解面向对象 Python语言基础 集合的
  • Java学习--JDBC操作数据库(直析操作)

    1 了解JDBC的常用类和接口 DriverManager类 用来管理数据库中的所有驱动程序 Connection接口 代表与特定的数据库的连接 Statement接口 用于创建向数据库中传递SQL语句的对象 PreparedStateme
  • -day25--mysql入门

    第四模块 MySQL数据库 数据库管理系统 DBMS 专注于帮助开发者解决数据存储的问题 这样开发者就可以把主要精力放在实现业务功能上了 业内有很多的的数据库管理系统产品 例如 MySQL 原来是sun公司 后来被甲骨文收购 现在互联网企业
  • 排序算法(java版本)

    1 直接插入排序 1 基本思想 在要排序的一组数中 假设前面 n 1 n gt 2 个数已经是排 好顺序的 现在要把第n个数插到前面的有序数中 使得这n个数 也是排好顺序的 如此反复循环 直到全部排好顺序 2 实例 3 用java实现 pa
  • 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK2038 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MDd_DynamicDe

    系列文章目录 文章目录 系列文章目录 前言 一 错误原因 二 解决问题 在这里插入图片描述 https img blog csdnimg cn a8ce751feae54668aa54ffe2e0031560 png 前言 严重性 代码 说
  • 2023年网络安全考试试题,背下来通过率99%

    1 关于数据使用说法错误的是 A 在知识分享 案例中如涉及客户网络数据 应取敏感化 不得直接使用 B 在公开场合 公共媒体等谈论 传播或发布客户网络中的数据 需获得客户书面授权或取敏感化 公开渠道获得的除外 C 客户网络数据应在授权范围内使
  • clang+llvm+linux x86平台交叉编译arm64

    下载工具链 bin bash workPATH pwd toolchain mkdir p workPATH cd workPATH URL LLVM https github com llvm llvm project releases
  • 算法训练营第十一天(7.22)

    目录 LeeCode20 Valid Parentheses LeeCode1047 Remove All Adjacent Duplicates In String LeeCode150 Evaluate Reverse Polish N
  • 第三章 3.1节练习 & 3.2.2节练习

    练习3 1 使用恰当的using声明重做1 4 1节 11页 和2 6 2节 67页 的练习 解答 这里就不写代码了 因为可以using命名空间或者空间中的对应函数 可以出现很多种组合 可以按照自己喜欢或熟悉的方式来写 练习3 2 编写一段
  • python 面向对象 超级详细全面讲解

    如有错误 欢迎留言指出讨论 1 面向对象和面向过程 1 1 面向过程注重的是结果 从结果出发去考虑问题的实现步骤 1 2 面向对象注重的是设计 从现实生活的角度 从设计的角度去考虑问题的实现步骤 1 3 虽然2种思想的目的都是为了做出一个程
  • 00后视频审核员,3个月顺利转行车载测试,他说你也能行!

    21年夏天毕业后 自觉比较社恐的我去找了一份看似清闲又不用和逼人打交道太多的工作 原本以为这份工作会成为我的庇佑所 没想到也是一地鸡毛 是的 我是一个视频审核 顾名思义 作为一个视频审核员 毫无疑问我的工作就是看视频 也许有人会说 就看看视
  • numpy中np.array()功能

    功能 将数据转化为矩阵 a 1 2 3 4 5 6 7 8 9 b np array a c np asarray a a 2 1 print a print b print c 从中我们可以看出np array与np asarray功能是
  • JAVA并发队列

    Java并发队列 在并发队列上JDK提供了两套实现 一个是以ConcurrentLinkedQueue为代表的高性能队列 一个是以BlockingQueue接口为代表的阻塞队列 无论哪种都继承自Queue 一 ConcurrentLinke
  • 【Hbase 05】Hbase表的设计原则与优化方案

    这里说一下Hbase在使用过程中的表设计原则与优化方案 如果你是运维或者开发兼顾环境的工作 也许比较受用 话不多说 我们直接开始说优化的内容 一 表设计原则 1 行键设计 行键在设计的时候要尽量的散列 例如可以考虑使用哈希 加密算法等使结果
  • 在Webpack 5 中如何进行 CSS 常用配置?

    本文摘要 主要通过实操讲解运用Webpack 5 CSS常用配置的方法步骤 前文已谈到可以通过配置 css loader 和 style loader 使 webpack5 具有处理 CSS 资源的能力 css loader 首先会分析出各
  • 【线性代数】向量组的线性相关性

    文章目录 向量组及其线性组合 一 向量 二 线性表示 1 线性组合的定义 2 线性表示的定义 3 线性表示的充要条件 三 向量组等价 1 向量组等价定义 2 向量组线性表示的充要条件 3 向量组等价的充要条件 4 向量组线性表示的必要条件
  • 如何设计企业节点的『工业互联网标识解析系统』

    一 星火 链网 体系架构 星火 链网 以节点形式进行组织互联互通 其中包括三类节点 超级节点 骨干节点 业务节点 其底层采用 1 N 主从链群架构 支持同构和异构区块链接入主链 在全国重点区域部署 星火 链网 超级节点 作为国家链网顶层 提
  • Waffle使用初体验

    一 什么是Waffle Waffle是什么呢 我们直接看其文档上的介绍 Waffle is a library for writing and testing smart contracts Sweeter simpler and fast