Product
Introducing License Enforcement in Socket
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
ethereum-waffle
Advanced tools
Library for writing and testing smart contracts.
Sweeter and simpler than truffle.
Works with ethers-js. Tastes best with ES6.
To start using with npm, type:
npm i ethereum-waffle
or with Yarn:
yarn add ethereum-waffle
Below is example contract written in Solidity. Place it in contracts
directory of your project:
pragma solidity ^0.5.1;
import "../BasicToken.sol";
contract BasicTokenMock is BasicToken {
constructor(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
}
}
Belows is example test written for the contract above written with Waffle. Place it in test
directory of your project:
import chai from 'chai';
import {createMockProvider, deployContract, getWallets, solidity} from 'ethereum-waffle';
import BasicTokenMock from './build/BasicTokenMock';
chai.use(solidity);
const {expect} = chai;
describe('Example', () => {
let provider;
let token;
let wallet;
let walletTo;
beforeEach(async () => {
provider = createMockProvider();
[wallet, walletTo] = await getWallets(provider);
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
});
it('Assigns initial balance', async () => {
expect(await token.balanceOf(wallet.address)).to.eq(1000);
});
it('Transfer adds amount to destination account', async () => {
await token.transfer(walletTo.address, 7);
expect(await token.balanceOf(wallet.address)).to.eq(993);
expect(await token.balanceOf(walletTo.address)).to.eq(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 from empty account', async () => {
const tokenFromOtherWallet = contractWithWallet(token, walletTo);
await expect(tokenFromOtherWallet.transfer(wallet.address, 1))
.to.be.revertedWith('Not enough balance on sender account');
});
});
To compile contracts simply type:
npx waffle
To compile using custom configuration file:
npx waffle config.json
Example configuration file looks like this:
{
"sourcesPath": "./custom_contracts",
"targetPath": "./custom_build",
"npmPath": "./custom_node_modules"
}
To run test type in the console:
mocha
For convince, you can add a task to your package.json
. In the sections scripts
, add following line:
"test": "waffle && test"
Now you can build and test your contracts with one command:
npm test
Import solidity files from solidity files form npm modules that you added to your project, e.g:
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
Create a mock provider (no need to run any tests!) and test your contracts against it, e.g.:
provider = createMockProvider();
Get wallets you can use to sign transactions:
[wallet, walletTo] = await getWallets(provider);
Deploy a contract:
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
Link a library:
myLibrary = await deployContract(wallet, MyLibrary, []);
link(LibraryConsumer, 'path/to/file:MyLibrary.sol:MyLibrary', myLibrary.address);
libraryConsumer = await deployContract(wallet, LibraryConsumer, []);
A set of sweet chai matchers, makes your test easy to write and read. Below couple of examples.
expect(await token.balanceOf(wallet.address)).to.eq(993);
Available matchers for BigNumbers are: equal
, eq
, above
, below
, least
, most
.
await expect(token.transfer(walletTo.address, 7))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, walletTo.address, 7);
await expect(token.transfer(walletTo.address, 1007)).to.be.reverted;
await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith('Insufficient funds');
expect('0x28FAA621c3348823D6c6548981a19716bcDc740e').to.be.properAddress;
expect('0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5').to.be.properPrivateKey;
expect('0x70').to.be.properHex(2);
await expect(() => myContract.transferWei(receiverWallet.address, 2)).to.changeBalance(receiverWallet, 2);
Note: transaction call should be passed to the expect as a callback (we need to check the balance before the call). The matcher can accept numbers, strings and BigNumbers as a balance change, while the address should be specified as a wallet.
changeBalance calls should not be chained. If you need to chain it, you probably want to use changeBalances matcher.
await expect(() => myContract.transferWei(receiverWallet.address, 2)).to.changeBalances([senderWallet, receiverWallet], [-2, 2]);
By default, Waffle uses solcjs. Solcjs is solidity complier cross-complied to javascript. It is slow, but easy to install. As an alternative, you can use the original Solidity compiler, which is faster. There are two options:
This options is pretty easy to install especially if you have docker installed. This is recommended option. If you don't have docker follow instructions.
Pull solc docker container tagged with version you are interested in, for example for version 0.4.24 it will be:
docker pull ethereum/solc:0.4.24
Than setup compiler in your waffle configuration file:
{
...
"compiler": "dockerized-solc",
"docker-tag": "0.4.24"
}
Default docker tag is latest
.
You can now run tests in docker.
This option is by far the fastest but requires you to install native solidity. If you need a legacy version that might be somewhat complicated and require you to build solidity
from sources.
You can find detailed installation instructions for native solc
in (documentation)[https://solidity.readthedocs.io/en/latest/installing-solidity.html#binary-packages].
You need to install version compatible with your sources. If you need latest version that is pretty straight forward. See Installation instructions below.
To install lastest versions on MacOS:
brew install solidity
To install other versions, it seems that currently it easiest to build from source:
To install lastest versions on Ubuntu:
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install solc
Setup compiler in your waffle configuration file:
{
...
"compiler": "native"
}
To do some detective work and figure out command for particular version go here:
You can now run tests with native solc, eg:
npx waffle
You can setup version which solidity compiler version you would like to use with solcjs
in waffle configuration file, e.g.:
{
...
"solcVersion": "v0.4.24+commit.e67f0147"
}
Version naming is somewhat unintuitive. You can deduce version name from [list available here] (https://ethereum.github.io/solc-bin/bin/list.json).
Note: To make end to end test pass, you need to have docker installed, up and running.
To run test type:
yarn test
FAQs
Sweeter, faster and simpler than truffle.
The npm package ethereum-waffle receives a total of 31,725 weekly downloads. As such, ethereum-waffle popularity was classified as popular.
We found that ethereum-waffle demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
Product
We're launching a new set of license analysis and compliance features for analyzing, managing, and complying with licenses across a range of supported languages and ecosystems.
Product
We're excited to introduce Socket Optimize, a powerful CLI command to secure open source dependencies with tested, optimized package overrides.