I couldn’t find a complete project setup guide with forge that satisfied my use-case so I made one. And by complete I mean one that does:
- Build, test, debug
Here’s an opinionated guide on how to setup forge, its roughly the same as the github readme and exists here solely as an SEO funnel.
Uses vscode + eslint plugin + solidity plugin.
- remappings.txt for vscode solidity linter
- foundry.toml to config forge
- Uses forge to compile, test, and debug.
- Uses a custom JS script to deploy, see deploy.js.
I prefer to write the deployment scripts as programatically as possible on a widely supported language as every deployment itself is unique, and sometimes there’s inter-dependencies between contracts.
- Deploy contract A
- Deploy contract B
- Call addOwner on B with A’s address
This is overly tricky with bash for me, and would require a LOT of unreadable (and error-prone) commands-line composition with jq and awk to achieve that with the default
Building and testing
forge build forge test # forking from existing state # -vvv = very very verbose forge test -f http://127.0.0.1:8545 -vvv # To access the debugger forge run --debug src/test/Contract.t.sol --sig "testExample()"
.env and fill it out with correct details.
node --experimental-json-modules scripts/deploy.js
Forge has a very useful in-built etherscan verification utility.
# For list of compiler versions https://etherscan.io/solcversions forge verify-contract --compiler-version v0.8.12+commit.f00d7308 [CONTRACT ADDRESS] --constructor-args <ARGS> --num-of-optimizations 200 [CONTRACT_PATH:CONTRACT_NAME] [ETHERSCAN_API_KEY] # To check verification status forge verify-check [GUID] [ETHERSCAN_KEY]
If you have multiple contracts with
pragma abiencoderv2, there is a possibility that you can’t verify your contracts on etherscan, there’s an open issue on this.
The caveat to the approach above is that you have to have to copy the libraries in
node_modules and make sure the path matches as it doesn’t read remappings.
cp -r lib/openzeppelin-contracts node_modules/@openzeppelin mv node_modules/@openzeppelin/contracts/* node_modules/@openzeppelin multisol src/Contract.sol