forge-build - Build the project's smart contracts.
forge build
or forge b
[options]
Build the project's smart contracts.
The command will try to detect the latest version that can compile your project by looking at the version requirements of all your contracts and dependencies.
You can override this behaviour by passing --no-auto-detect
. Alternatively, you can pass --use <SOLC_VERSION>
.
If the command detects that the Solidity compiler version it is using to build is not installed,
it will download it and install it in ~/.svm
. You can disable this behavior by passing --offline
.
The build is incremental, and the build cache is saved in cache/
in the project root by default. If you
want to clear the cache, pass --force
, and if you want to change the cache directory, pass --cache-path <PATH>
.
It is possible to choose sources to build by specifying multiple path options (can be paths to source directories or files).
There are three build modes:
- Just compilation (default): Builds the project and saves the contract artifacts in
out/
(or the path specified by--out <PATH>
). - Size mode (
--sizes
): Builds the project, displays the size of non-test contracts and exits with code 1 if any of them are above the size limit. - Name mode (
--names
): Builds the project, displays the names of the contracts and exits.
You can enable the optimizer by passing --optimize
, and you can adjust the number of optimizer runs by passing --optimizer-runs <RUNS>
.
You can also opt-in to the Solidity IR compilation pipeline by passing --via-ir
. Read more about the IR pipeline in the Solidity docs.
By default, the optimizer is enabled and runs for 200 cycles.
Many projects use the solc optimizer, either through the standard compilation pipeline or the IR pipeline. But in some cases, the optimizer can significantly slow down compilation speeds.
A config file for a project using the optimizer may look like this for regular compilation:
[profile.default]
solc-version = "0.8.17"
optimizer = true
optimizer-runs = 10_000_000
Or like this for via-ir
:
[profile.default]
solc-version = "0.8.17"
via_ir = true
To reduce compilation speeds during development and testing, one approach is to have a lite
profile that has the optimizer off and use this for development/testing cycle. The updated config file for regular compilation may look like this:
[profile.default]
solc-version = "0.8.17"
optimizer = true
optimizer-runs = 10_000_000
[profile.lite]
optimizer = false
Or like this for via-ir
:
[profile.default]
solc-version = "0.8.17"
via_ir = true
[profile.lite.optimizer_details.yulDetails]
optimizerSteps = ''
When setup like this, forge build
(or forge test
/ forge script
) still uses the standard profile, so by default a forge script
invocation will deploy your contracts with the production setting. Running FOUNDRY_PROFILE=lite forge build
(and again, same for the test and script commands) will use the lite profile to reduce compilation times.
There are additional optimizer details you can configure, see the Additional Optimizer Settings section below for more info.
You can add extra output from the Solidity compiler to your artifacts by passing --extra-output <SELECTOR>
.
The selector is a path in the Solidity compiler output, which you can read more about in the Solidity docs.
You can also write some of the compiler output to separate files by passing --extra-output-files <SELECTOR>
.
Valid selectors for --extra-output-files
are:
metadata
: Written as ametadata.json
file in the artifacts directoryir
: Written as a.ir
file in the artifacts directoryirOptimized
: Written as a.iropt
file in the artifacts directoryewasm
: Written as a.ewasm
file in the artifacts directoryevm.assembly
: Written as a.asm
file in the artifacts directory
The command can be run in watch mode by passing --watch [PATH...]
, which will rebuild every time a
watched file or directory is changed. The source directory is watched by default.
Sparse mode only compiles files that match certain criteria.
By default, this filter applies to files that have not been changed since the last build, but for commands that take file filters (e.g. forge test), sparse mode will only recompile files that match the filter.
Sparse mode is opt-in until the feature is stabilized. To opt-in to sparse mode and try it out, set sparse_mode
in your configuration file.
The optimizer can be fine-tuned with additional settings. Simply set the optimizer_details
table in your configuration file. For example:
[profile.default.optimizer_details]
constantOptimizer = true
yul = true
[profile.default.optimizer_details.yulDetails]
stackAllocation = true
optimizerSteps = 'dhfoDgvulfnTUtnIf'
See the compiler input description documentation
for more information on available settings (specifically settings.optimizer.details
).
You can control how revert strings are generated by the compiler. By default, only user supplied revert strings are included in the bytecode, but there are other options:
strip
: Removes all revert strings (if possible, i.e. if literals are used) keeping side-effects.debug
: Injects strings for compiler-generated internal reverts, implemented for ABI encoders V1 and V2 for now.verboseDebug
: Appends further information to user-supplied revert strings (not yet implemented).
Solidity's built-in model checker is an opt-in module that can be enabled via the ModelChecker
object.
See Compiler Input Description settings.modelChecker
and the model checker's options.
The module is available in solc
release binaries for OSX and Linux. The latter requires the z3 library version [4.8.8, 4.8.14] to be installed in the system (SO version 4.8).
Similarly to the optimizer settings above, the model_checker
settings must be prefixed with the profile they correspond to: [profile.default.model_checker]
belongs to the [profile.default]
.
## foundry.toml
[profile.default.model_checker]
contracts = { '/path/to/project/src/Contract.sol' = [ 'Contract' ] }
engine = 'chc'
timeout = 10000
targets = [ 'assert' ]
The fields above are recommended when using the model checker.
Setting which contract should be verified is extremely important, otherwise all available contracts will be verified which can consume a lot of time.
The recommended engine is chc
, but bmc
and all
(runs both) are also accepted.
It is also important to set a proper timeout (given in milliseconds), since the default time given to the underlying solvers may not be enough.
If no verification targets are given, only assertions will be checked.
The model checker will run when forge build
is invoked, and will show findings as warnings if any.
--names
Print compiled contract names.
--sizes
Print compiled non-test contract sizes, exiting with code 1 if any of them are above the size limit.
--skip
Skip compilation of non-essential contract directories like test or script (usage --skip test
).
[PATHS]...
Build source files from specified paths.
{{#include core-build-options.md}}
{{#include watch-options.md}}
{{#include common-options.md}}
-
Build the project:
forge build
-
Build the project with solc 0.6.0:
forge build --use solc:0.6.0
-
Build the project with additional artifact output:
forge build --extra-output evm.assembly
-
Build the project in watch mode:
forge build --watch
-
Build source files from
test/invariant
directory andtest/RegressionTest.sol
:forge build test/invariant test/RegressionTest.sol