While Waffle works well enough without any configurations, advanced users might want to excert more control over what happens when they use Waffle in their projects.
This is why we made it very easy to configure Waffle to meet your needs. All you need to do is create a waffle.json
file inside your project and point waffle to it.
First create your waffle.json
configuration file:
{
"compilerType": "solcjs",
"compilerVersion": "0.6.2",
"sourceDirectory": "./src",
"outputDirectory": "./build"
}
Note
Each configuration is optional.
Afterwards update your package.json
build script:
Note
Since Waffle 3.0.0 it recognises waffle.json
as the default configuration file. If your configuration file is called waffle.json
, it's possible to use just waffle
to build contracts.
Waffle 3.0.0
{
"scripts": {
"build": "waffle"
}
}
Waffle 2.5.0
{
"scripts": {
"build": "waffle waffle.json"
}
}
Configuration options:
sourceDirectory
outputDirectory
nodeModulesDirectory
cacheDirectory
compilerType
compilerVersion
compilerAllowedPaths
compilerOptions
outputHumanReadableAbi
outputType
You can specify a custom path to the directory containing your smart contracts. Waffle uses ./contracts
as the default value for sourceDirectory
. The path you provide will be resolved relative to the current working directory.
Example:
{
"sourceDirectory": "./custom/path/to/contracts"
}
You can specify a custom path to the directory to which Waffle saves the compilation output. Waffle uses ./build
as the default value for outputDirectory
. The path you provide will be resolved relative to the current working directory.
Example:
{
"outputDirectory": "./custom/path/to/output"
}
You can specify a custom path to the node_modules
folder which Waffle will use to resolve third party dependencies. Waffle uses ./node_modules
as the default value for nodeModulesDirectory
. The path you provide will be resolved relative to the current working directory.
For more information about third party libraries, see third-party
.
Example:
{
"nodeModulesDirectory": "./custom/path/to/node_modules"
}
When compiling using solcjs
and using a non-default compilerVersion
Waffle downloads the necessary solcjs
binary from a remote server. This file is cached to speed up subsequent runs. You can specify a custom path to the directory in which caches are saved. Waffle uses ./cache
as the default value for cacheDirectory
. The path you provide will be resolved relative to the current working directory.
Example:
{
"cacheDirectory": "./custom/path/to/cache"
}
Specifies the compiler to use. For more information see: compile-times
. Allowed values:
solcjs
native
dockerized-solc
dockerized-vyper
Waffle uses solcjs
as the default value for compilerType
.
Example:
{
"compilerType": "dockerized-solc"
}
Specifies the version of the compiler. Should be a semver string like 0.5.9
. You can use it with "compilerType": "solcjs"
or "compilerType": "dockerized-solc"
.
When using "compilerType": "solcjs"
you can also specify the exact commit that will be used or a path to a specific solc module dependency.
To find a specific commit please consult the list of available solc versions.
Examples:
{
"compilerType": "dockerized-solc",
"compilerVersion": "0.4.24"
}
{
"compilerType": "solcjs",
"compilerVersion": "v0.4.24+commit.e67f0147"
}
{
"compilerType": "solcjs",
"compilerVersion": "./node_modules/solc"
}
The solc
compiler has restrictions on paths it can access for security reasons. The value of compilerAllowedPaths
will be passed as a command line argument: solc --allow-paths <VALUE>
.
This is especially useful if you are doing a monorepo setup with Lerna, see: lerna
.
Example:
{
"compilerAllowedPaths": ["../contracts"]
}
You can customize the behaviour of solc
by providing custom settings for it. All of the information is provided in the Solidity documentation. Value of the compilerOptions
configuration setting will be passed to solc
as settings
.
For detailed list of options go to solidity documentation (sections: 'Setting the EVM version to target', 'Target options' and 'Compiler Input and Output JSON Description').
Example:
{
"compilerOptions": {
"evmVersion": "constantinople"
}
}
See: klab
.
Waffle supports Human Readable Abi.
In order to enable its output, you need to set outputHumanReadableAbi
to true
in your config file:
{
"outputHumanReadableAbi": true
}
For the compiled contracts you will now see the following in the output:
{
"humanReadableAbi": [
"constructor(uint256 argOne)",
"event Bar(bool argOne, uint256 indexed argTwo)",
"event FooEvent()",
"function noArgs() view returns(uint200)",
"function oneArg(bool argOne)",
"function threeArgs(string argOne, bool argTwo, uint256[] argThree) view returns(bool, uint256)",
"function twoReturns(bool argOne) view returns(bool, uint256)"
]
}
Waffle supports typechain artifacts generation. To enable typed artifacts generation you should set typechainEnabled
property to true
. You are also able to define target folder for your artifacts by defining typechainOutputDir
property, which is set to ./types
by default. Property typechainOutputDir
is a path relative to outputDirectory
.
Example:
{
"typechainEnabled": true,
"typechainOutputDir": "typechain"
}
Waffle supports the following configuration file formats:
JSON:
{
"sourceDirectory": "./src/contracts",
}
JavaScript:
module.exports = {
sourceDirectory: './src/contracts'
}
The configuration can even be a promise
module.exports = Promise.resolve({
sourceDirectory: './src/contracts'
})
Hint
This is a powerful feature if you want to asynchronously load different compliation configurations in different environments. For example, you can use native solc in CI for faster compilation, while deciding the exact solc-js version locally based on the contract versions being used. Since many of those operations are asynchronous, you'll most likely be returning a Promise to waffle to handle.
See compilerVersion
.
Waffle output should be compatible with Truffle by default.
See compilerOptions
.
The default compilation process is not compatible with KLAB (a formal verification tool, see: https://github.com/dapphub/klab). To compile contracts to work with KLAB one must:
- Set appropriate compiler options, i.e.:
compilerOptions: {
outputSelection: {
"*": {
"*": [ "evm.bytecode.object", "evm.deployedBytecode.object",
"abi" ,
"evm.bytecode.sourceMap", "evm.deployedBytecode.sourceMap" ],
"": [ "ast" ]
},
}
}
2. Set appropriate output type. We support two types: one (default) generates a single file for each contract and the other (KLAB friendly) generates one file (Combined-Json.json) combining all contracts. The latter type does not meet (in contrary to the first one) all official solidity standards since KLAB requirements are slightly modified. Set the output in the config file:
Possible options are:
- `'multiple'`: a single file for each contract;
- `'combined'`: one KLAB friendly file;
- `'all'`: generates both above outputs;
- `'minimal'`: a single file for each contract with minimal information (just abi and bytecode).
Note
'minimal' option was introduced in Waffle 3.0.0.
{
"outputType": "combined"
}
An example of full KLAB friendly config file:
module.exports = {
compilerType: process.env.WAFFLE_COMPILER,
outputType: 'all',
compilerOptions: {
outputSelection: {
"*": {
"*": [ "evm.bytecode.object", "evm.deployedBytecode.object",
"abi" ,
"evm.bytecode.sourceMap", "evm.deployedBytecode.sourceMap" ],
"": [ "ast" ]
},
}
}
};
Waffle works well with mono-repositories. It is enough to set up a common nodeModulesDirectory
in the configuration file to make it work. We recommend using yarn workspaces and wsrun for monorepo management.
Waffle works with lerna, but requires additional configuration. When lerna cross-links npm packages in monorepo, it creates symbolic links to the original catalog. They lead to sources files located beyond allowed paths. This process breaks compilation with native solc.
If you see the following message in your monorepo setup:
contracts/Contract.sol:4:1: ParserError: Source ".../monorepo/node_modules/YourProjectContracts/contracts/Contract.sol" not found: File outside of allowed directories.
import "YourProjectContracts/contracts/Contract.sol";
you probably need to add allowedPath to your waffle configuration.
Assuming you have the following setup:
/monorepo
/YourProjectContracts
/contracts
/YourProjectDapp
/contracts
Add to waffle configuration in YourProjectDapp:
{
"compilerAllowedPaths": ["../YourProjectContracts"]
}
That should solve a problem.
Currently Waffle does not support a similar feature for dockerized solc.