This is a modern Solidity template for Ethereum smart contracts. It combines two extremely powerful frameworks:
- Foundry - for Unit tests written in Solidity (contracts/test/).
- Hardhat - for Integration tests written in Typescript (integration/).
This template optimizes and cleans up using these frameworks together (e.g. no remappings.txt
or /lib
submodules, using one foundry.toml as a source of truth for options). Dependencies are all managed through NPM.
Utilizing both frameworks allows you to comprehensively test every scenario, which should always be the case when planning to deploy immutable code. Both layers of testing also gives other developers a reference for how they should interact with your contracts:
-
On-chain developers writing contracts that call these contracts can refer to your Unit Test files to see the expected usage in Solidity.
-
Off-chain developers writing clients that call these contracts can refer to your Integration Test files to see the expected usage in JavaScript (TypeScript) and Ethers.js.
These frameworks also offer some advanced tools for contract debugging, deployment, gas measurements, etc.
Other features of this template are linting rules for Solidity and TypeScript, a developer guide for new contributors to your project, a LICENSE sample which can be changed, a sample CLI for contract deployment and interactions, documentation generation from NatSpec comments, and useful GitHub Actions already configured.
integration/
|- counter.test.ts - "Integration tests with Hardhat"
scripts/
|- console.ts - "CLI for contracts"
|- deploy.ts - "Contract deployment functions"
contracts/
|- interfaces/
|--- ICounter.sol - "Interface contract"
|- test/
|--- Counter.t.sol - "Unit tests with Foundry"
|- Counter.sol - "Implementation contract"`
.env - "Real environment vars"
.env.example - "Example environment vars"
.eslintignore - "Ignore list for eslint"
.eslintrc - "Configure eslint"
.gitignore - "Ignore list for Git"
.solcover.js - "Configure coverage"
.solhint.json - "Configure Solidity linter"
.prettierignore - "Ignore list for Prettier"
.prettierrc.json - "Configure Prettier"
foundry.toml - "Configure Foundry"
hardhat.config.ts - "Configure Hardhat"
LICENSE - "Software license"
package.json - "Node dependencies"
slither.config.json - "Configure Slither"
tsconfig.json - "Configure Typescript"
--- (not an extensive list of all files) ---
git clone https://github.com/mattstam/solidity-template.git && cd solidity-template
npm install -g npm
cp .env.example .env
Fill in at least your MNEMONIC
npm i
curl -L https://foundry.paradigm.xyz | bash
Then, in a new terminal session or after reloading your PATH
, run this to get
the latest forge
and cast
binaries:
foundryup
forge test
This will run everything in contracts/test/, which utilizes Forge to test contract code.
npm run test
This will run everything in integration/, which utilizes Hardhat to tests for full usage scenarios.
Create a .env file matching the variables seen in .env.example.
Getting fully prepared may involve getting a INFURA_API_KEY
by signing up, and getting some test ETH on your target network via a facet.
Then run:
npm run deploy -- --network goerli
This will automatically update deployments.json, which gets exported with your NPM package. It will also become the default address to use when interacting with your contracts with the CLI.
npm run doc
Sets up API docs from the NatSpec comments in your contract interfaces (ignoring implementations and libraries).
If desired, this can be updated to included all contract comments, and the path can be updated to a different location (such as if you want a seperate docs
repository for your project).
Foundry is a blazing fast, portable, and modular toolkit for Ethereum application development. It consists of:
- Forge: Framework for Unit / Fuzz testing written in Solidity.
- Cast: EVM interactions for contracts, transaction handling, and reading on-chain data.
- Anvil: A local testnet node with network forking capabilities.
Configuration details can be found in foundry.toml.
Hardhat is a complete Ethereum development environment. The integration tests run on the Hardhat network, with each test written in JavaScript (TypeScript), utilizing the Ethers.js library, and the Mocha testing framework.
Hardhat can also be extended (see the full plugin list). This project makes use of:
- Hardhat Waffle - test assertions with Chai matchers.
- Hardhat Ethers - integration with Ethers.js.
- Hardhat Solhint - integration with the Solidity language Solhint linter.
- Hardhat Gas Reporter - gas cost summary of contract calls.
- Hardhat Tracer - contract name tag for logs and advanced debugging.
- Hardhat Contract Sizer - show output size of contracts.
- Hardhat Etherscan - verify contract source code on Etherscan.
- Hardhat Dodoc - documentation generation from NatSpec.
Configuration details can be found in hardhat.config.ts, which inherits from foundry.toml.
- Solidity Visual Developer
- Solidity Language & Themes (only)
- Solidity (by Hardhat authors)
- Solidity (by Juan Blanco)
- Prettier
All contract addresses for each network are stored in deployments.json.
The code in this project is licensed under the MIT License.