Compiling
The OpenZeppelin CLI integrates the Solidity compiler to seamlessly compile your Solidity contracts into Ethereum Virtual Machine (EVM) bytecode.
This guide covers how compiling works, its different options, and the output format.
Running the Compiler
Most CLI commands, like oz deploy
or oz upgrade
, will automatically compile your projects smart contracts when required, so you don’t need to worry about doing this yourself.
However, you can also just run the compilation by itself, using the oz compile
command:
$ npx oz compile
When executed for the first time, all smart contracts in the contracts
directory will be compiled at once. Further invocations of compile
however will only compile contracts that have changed (along with their dependents), speeding up the process.
Settings
All compilation settings are passed directly to the Solidity compiler. Check out its documentation for more info on how each setting affects compilation.
Picking a Compiler Version
Each Solidity source files should be annotated with a version pragma that indicates which compiler versions can be used to compile it.
The CLI will parse all of these declarations and automatically select the latest compiler version that matches all your version pragmas. This single version will be the one used to compile all of your contracts.
It is often best to use permissive pragmas, such as ^0.5.0 or ^0.6.0 (which select the 0.5.x and 0.6.x lines of the compiler, respectively), and let the CLI do the rest.
|
Alternatively, you can also specify a compiler version when calling oz compile
by using the --solc-version
option:
$ npx oz compile --solc-version 0.5.14
In all cases, the selected Solidity compiler version will be automatically downloaded and saved to cache from the official distribution list. Once the version is set, subsequent compilations will use that same version.
For enhanced performance, you can install the native Solidity binaries on your machine: the CLI will automatically pick it up when compiling if it matches the target version. Massive speedups can be achieved by doing this, specially on large projects. Just make sure it’s available on your PATH !.
|
Picking an EVM Version
Each version of the Solidity compiler ships with a default EVM version, which corresponds to the mainnet EVM version at the time of release. The CLI will respect these defaults unless otherwise instructed.
In some occasions, it may be necessary to select a specific EVM version. This is achieved via the --evm-version
flag:
$ npx oz compile --evm-version berlin
Using the Optimizer
The Solidity compiler features an optional optimizer: it can produce smaller and more gas-efficient EVM bytecode, at the cost of making it harder to understand.
The optimizer is enabled or disabled with the --optimizer
option:
$ npx oz compile --optimizer on
For fine tuning, you can also pass the --optimizer-runs
option. This number should be an estimate of how many times you expect your smart contract to be called: pass 1 for one-offs, or a higher number for regularly used contracts. The default value is 200.
$ npx oz compile --optimizer on --optimizer-runs 100
Don’t worry if you’re not sure what value to pass to --optimizer-runs : the gains achieved by using this parameter correctly are very limited.
|
Saving Your Settings
All compilation settings, including compiler version, EVM version and optimizer configuration are stored in your project configuration file, will be used in all successive compilations.
To modify these settings, run oz compile
with the newly desired values, or simply edit the configuration file manually.
Compilation Results
Storing Compiled Artifacts
The output of the compiler is a number of .json
files (one per compiled contract), which hold all relevant information: compiler settings, copies of the source, and most importantly, the resulting ABI and bytecode. These files are stored in the build/contracts
directory, which the CLI will create for you automatically.
These files can be large, and since compilation is a fast process it’s often a good idea to add this directory to your
|
Loading Your Contracts
The format of the .json
artifacts is standard, and compatible with all major smart contract tools out there, such as Truffle, Buidler, and Etherlime.
If you want to load your compiled contracts and interact with them from JavaScript code, we recommend using the OpenZeppelin Contract Loader:
const { setupLoader } = require('@openzeppelin/contract-loader');
const loader = setupLoader({
provider, // either a web3 provider or a web3 instance
defaultSender, // optional
});
// Load build/contracts/ERC20.json
const ERC20 = loader.web3.fromArtifact('ERC20');
// Deploy contract
const token = await ERC20.deploy().send();
// Query state and send transaction
const balance = await token.methods.balanceOf(sender).call();
await token.methods.transfer(receiver, balance).send({ from: sender });