Waffle
Library for writing and testing smart contracts.
README
Waffle
The most advanced framework for testing smart contracts.
Sweeter, simpler and faster.
Links
Website - https://getwaffle.io/
Documentation - https://ethereum-waffle.readthedocs.io/
Philosophy
Simpler: Minimalistic, few dependencies.
Sweeter: Nice syntax, easy to extend.
Faster: Strong focus on the speed of test execution.
Features:
Sweet set of chai matchers, e.g.:
expect(...).to.be.revertedWith('Error message')
expect(...).to.emit(contract, 'EventName').withArgs(...))
Importing contracts from npm modules working out of the box, e.g.:
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
Fixtures that help write fast and maintainable test suites, e.g.:
const {token} = await loadFixture(standardTokenWithBalance);
Customizable compilation options with native solc, dockerized solc and any version of solc-js loaded remotely at compiled time
Mocking smart contracts, e.g.:
const mockToken = await deployMockContract(wallet, IERC20.abi);
Support for promise-based configuration, e.g.:
use native solc binary for fast compilation in CI environment
use solc-js based on contract versions detected (async)
Support for TypeScript
Type-safe contract deployment and interactions with TypeChain
Documentation
Documentation is available here .
Installation:
To get started install ethereum-wafflewith yarn:
- ``` null
- yarn add --dev ethereum-waffle
- ```
Or if you prefer using npm:
- ``` null
- npm install --save-dev ethereum-waffle
- ```
Step by step guide
Add external dependency:
To add an external library install it using npm:
- ``` shell
- npm install @openzeppelin/contracts -D
- ```
or with yarn:
- ``` shell
- yarn add @openzeppelin/contracts -D
- ```
Note
Find this example in examples/basicand use it.
Example contract
Below is an example contract written in Solidity. Place it in contracts/BasicToken.solfile of your project:
- ``` solidity
- 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);
- }
- }
- ```
Example test
Below is an example test written for the contract above compiled with Waffle. Place it under test/BasicToken.test.tsfile in your project directory:
- ``` 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]);
- });
- });
- ```
Note: You will also need to install the following dependencies to run the example above:
- ``` shell
- yarn add mocha -D
- yarn add chai -D
- ```
Or with npm:
- ``` null
- npm i chai -D
- npm i mocha -D
- ```
Compiling
To compile your smart contracts run:
- ``` shell
- npx waffle
- ```
To compile using a custom configuration file run:
- ``` shell
- npx waffle config.json
- ```
Example configuration file looks like this (all fields optional):
- ``` json
- {
- "sourceDirectory": "./custom_contracts",
- "outputDirectory": "./custom_build",
- "nodeModulesDirectory": "./custom_node_modules"
- }
- ```
To enable generation of typechain artifacts:
- ``` json
- {
- "typechainEnabled": true
- }
- ```
Flattener
To flat your smart contracts run:
- ``` shell
- npx waffle flatten
- ```
In configuration file you can add optional field with path to flatten files:
- ``` json
- {
- "flattenOutputDirectory": "./custom_flatten"
- }
- ```
Running tests
To run the tests run the following command:
- ``` shell
- npx mocha
- ```
Adding an npm script
For convenience, you can add the following to your package.json:
- ``` null
- {
- ...,
- "scripts": {
- "test": "waffle && mocha"
- }
- }
- ```
Now you can build and test your contracts with one command:
- ``` shell
- npm test
- ```
Documentation
For detailed feature walkthrough checkout documentation .
Contributing
Contributions are always welcome, no matter how large or small. Before contributing, please read the code of conduct and contribution policy .
Before you issue pull request:
Make sure all tests and linters pass. Make sure you have test coverage for any new features.
Running tests
Note: To make end-to-end test pass, you need to:
have Docker installed, up and running
have Ethereum stable docker image pulled, if not run docker pull ethereum/solc:stable
have native solidity 0.5.* installed
To run tests type:
- ``` shell
- yarn test
- ```
To run linter type:
- ``` shell
- yarn lint
- ```
Building documentation
Install Sphinx to build documentation:
- ``` shell
- cd docs
- make html
- ```
Before building documentation for the first time you may have to install required python packages:
- ``` shell
- pip3 install -r docs/requirements.txt
- ```
Roadmap
See #155
License
Waffle is released under the MIT License .