Skip to content

Commit

Permalink
Readme update (#47)
Browse files Browse the repository at this point in the history
* add bullet points in documentation
* readme update
  • Loading branch information
marekkirejczyk committed Jan 12, 2019
1 parent cfbd67d commit fdee1b9
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 220 deletions.
223 changes: 6 additions & 217 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

Library for writing and testing smart contracts.

Sweeter and simpler than [truffle](https://github.com/trufflesuite/truffle).

Works with [ethers-js](https://github.com/ethers-io/ethers.js/). Tastes best with ES6.
Sweeter, simpler, faster. Works with [ethers-js](https://github.com/ethers-io/ethers.js/).
Documentation available [here](https://ethereum-waffle.readthedocs.io/en/latest/).

## Philosophy
* __Simpler__: minimalistic, a couple of helpers, matchers and tasks rather than a framework, few dependencies.
* __Sweeter__: Nice syntax, fast, easy to extend.
* __Faster__: Focus on the speed of tests execution, the goal is to have subsecond feedback loop when doing TDD with smart contracts.


## Versions and ethers compatibility
* Use version 0.2.3+ with ethers 3.* and solidity 4.*
Expand Down Expand Up @@ -133,222 +134,10 @@ Now you can build and test your contracts with one command:
npm test
```

## Features walkthrough

### Import contracts from npms
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
Create a mock provider (no need to run any tests!) and test your contracts against it, e.g.:
```js
provider = createMockProvider();
```

### Get example wallets
Get wallets you can use to sign transactions:
```js
[wallet, walletTo] = await getWallets(provider);
```

### Deploy contract
Deploy a contract:
```js
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
```

Link a library:
```js
myLibrary = await deployContract(wallet, MyLibrary, []);
link(LibraryConsumer, 'path/to/file:MyLibrary.sol:MyLibrary', myLibrary.address);
libraryConsumer = await deployContract(wallet, LibraryConsumer, []);
```

### Chai matchers
A set of sweet chai matchers, makes your test easy to write and read. Below couple of examples.

* Testing big numbers:
```js
expect(await token.balanceOf(wallet.address)).to.eq(993);
```
Available matchers for BigNumbers are: `equal`, `eq`, `above`, `below`, `least`, `most`.

* Testing what events where emitted with what arguments:
```js
await expect(token.transfer(walletTo.address, 7))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, walletTo.address, 7);
```
## Documentation
For detailed feature walkthrough checkout [documentation](https://ethereum-waffle.readthedocs.io/en/latest/).

* Testing if transaction was reverted:
```js
await expect(token.transfer(walletTo.address, 1007)).to.be.reverted;
```

* Testing if transaction was reverted with certain message:
```js
await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith('Insufficient funds');
```


* Testing if string is a proper address:
```js
expect('0x28FAA621c3348823D6c6548981a19716bcDc740e').to.be.properAddress;
```

* Testing if string is a proper secret:
```js
expect('0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5').to.be.properPrivateKey;
```

* Testing if string is a proper hex value of given length:
```js
expect('0x70').to.be.properHex(2);
```

* Testing whether the transaction changes balance
```js
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.

* Testing whether the transaction changes balance for multiple accounts
```js
await expect(() => myContract.transferWei(receiverWallet.address, 2)).to.changeBalances([senderWallet, receiverWallet], [-2, 2]);
```

## Fixtures
When testing code dependent on smart contracts it is often useful to have a specific scenario play out before every test. For example when testing an ERC20 token one might want to check that specific addresses can or cannot perform transfers. Before each of those tests however you have to deploy the ERC20 contract and maybe transfer some funds.

The repeated deployment of contracts might slow down the test significantly. This is why Waffle allows you to create fixtures - testing scenarios that are executed once and then remembered by making snaphots of the blockchain. This significantly speeds up the tests.

Example:
```js
import {expect} from 'chai';
import {loadFixture, deployContract} from 'ethereum-waffle';
import BasicTokenMock from './build/BasicTokenMock';

describe('Fixtures', () => {
async function fixture(provider, [wallet, other]) {
const token = await deployContract(wallet, BasicTokenMock, [
wallet.address, 1000
]);
return {token, wallet, other};
}

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

it('Transfer adds amount to destination account', async () => {
const {token, other} = await loadFixture(fixture);
await token.transfer(other.address, 7);
expect(await token.balanceOf(other.address)).to.eq(7);
});
});
```

Fixtures receive a provider and an array of wallets as an argument. By default the provider is obtained by calling `createMockProvider` and the wallets by `getWallets`. You can however override those by using a custom fixture loader.

```js
import {createFixtureLoader} from 'ethereum-waffle';

const loadFixture = createFixtureLoader(myProvider, myWallets);

// later in tests
await loadFixture((myProvider, myWallets) => {
// fixture implementation
});
```

## Fast compilation
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:
1) Dockerized solc
2) Native solc


### Dockerized solc (experimental)
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](https://www.docker.com/get-started).

Pull solc docker container tagged with version you are interested in, for example for version 0.4.24 it will be:
```sh
docker pull ethereum/solc:0.4.24
```

Than setup compiler in your waffle configuration file:
```js
{
...
"compiler": "dockerized-solc",
"docker-tag": "0.4.24"
}
```

Default docker tag is `latest`.

You can now run tests in docker.

### Native solc
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.

#### Installation instructions for latest version of solidity
##### MacOS
To install lastest versions on MacOS:
```sh
brew install solidity
```

To install other versions, it seems that currently it easiest to build from source:
1. Download sources from (release list on github)[https://github.com/ethereum/solidity/releases]
2. Follow installation instructions in the (documentation)[https://solidity.readthedocs.io/en/develop/installing-solidity.html#building-from-source]

##### Ubuntu
To install lastest versions on Ubuntu:
```sh
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install solc
```

##### Project setup
Setup compiler in your waffle configuration file:
```js
{
...
"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:
```sh
npx waffle
```


## Solcjs and version management
You can setup version which solidity compiler version you would like to use with `solcjs` in waffle configuration file, e.g.:
```js
{
...
"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).

## Contributing

Expand Down
6 changes: 3 additions & 3 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Works with ethers-js. Tastes best with ES6.

Philosophy:
-----------
Simpler: minimalistic, a couple of helpers, matchers and tasks rather than a framework, few dependencies.
Sweeter: Nice syntax, fast, easy to extend.
Faster: focus on the speed of tests execution, the goal is to have subsecond feedback loop when doing TDD with smart contracts
- Simpler: minimalistic, a couple of helpers, matchers and tasks rather than a framework, few dependencies.
- Sweeter: Nice syntax, fast, easy to extend.
- Faster: focus on the speed of tests execution, the goal is to have subsecond feedback loop when doing TDD with smart contracts


Versions and ethers compatibility
Expand Down

0 comments on commit fdee1b9

Please sign in to comment.