Appendix C: Solidity Development Environment Setup
This appendix guides you through setting up a complete Solidity smart contract development environment. You will configure two professional-grade toolchains (Hardhat and Foundry), a browser-based alternative (Remix), and the supporting infrastructure for deploying and verifying contracts on testnets.
C.1 Node.js Installation
Both Hardhat and most Ethereum JavaScript tooling require Node.js. Install the LTS (Long Term Support) version (20.x or later).
Windows
- Download the LTS installer from nodejs.org.
- Run the installer with default settings (ensure "Add to PATH" is selected).
- Verify:
node --version # v20.x.x or later
npm --version # 10.x.x or later
macOS
brew install node@20
node --version
npm --version
Linux (Ubuntu/Debian)
# Using NodeSource repository for latest LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node --version
npm --version
Alternative: nvm (Recommended for Multiple Projects)
Node Version Manager lets you switch between Node versions:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Restart terminal, then:
nvm install 20
nvm use 20
nvm alias default 20
C.2 Hardhat Project Setup
Hardhat is the most widely used Ethereum development framework. It provides compilation, testing, deployment, and debugging tools with an extensible plugin system.
Creating a New Hardhat Project
mkdir my-contracts
cd my-contracts
npm init -y
npm install --save-dev hardhat
npx hardhat init
Select "Create a JavaScript project" (or TypeScript if you prefer). Accept the default options. Hardhat will scaffold:
my-contracts/
contracts/ # Solidity source files
ignition/ # Deployment modules (Hardhat Ignition)
test/ # Test files
hardhat.config.js # Configuration
package.json
Installing Essential Plugins
npm install --save-dev \
@nomicfoundation/hardhat-toolbox \
@nomicfoundation/hardhat-verify \
dotenv
The hardhat-toolbox package bundles ethers.js v6, Chai for assertions, Hardhat Network Helpers, Hardhat coverage, and gas reporting.
Configuration
Edit hardhat.config.js:
require("@nomicfoundation/hardhat-toolbox");
require("@nomicfoundation/hardhat-verify");
require("dotenv").config();
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: "0.8.24",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
networks: {
hardhat: {
// Local Hardhat Network (default)
},
sepolia: {
url: `https://eth-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
accounts: process.env.DEPLOYER_PRIVATE_KEY
? [process.env.DEPLOYER_PRIVATE_KEY]
: [],
},
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
},
};
Environment Variables
Create a .env file in the project root:
ALCHEMY_API_KEY=your_alchemy_api_key
DEPLOYER_PRIVATE_KEY=your_testnet_private_key
ETHERSCAN_API_KEY=your_etherscan_api_key
Security Warning: The
DEPLOYER_PRIVATE_KEYshould be a testnet-only account with no mainnet funds. Never store a mainnet private key in a.envfile. Add.envto.gitignoreimmediately.
Basic Workflow
# Compile contracts
npx hardhat compile
# Run tests
npx hardhat test
# Run a local blockchain node
npx hardhat node
# Deploy to local network
npx hardhat ignition deploy ./ignition/modules/Lock.js
# Deploy to Sepolia testnet
npx hardhat ignition deploy ./ignition/modules/Lock.js --network sepolia
Writing Your First Test
// test/Lock.js
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Lock", function () {
it("should set the unlock time", async function () {
const ONE_YEAR = 365 * 24 * 60 * 60;
const unlockTime = Math.floor(Date.now() / 1000) + ONE_YEAR;
const lockedAmount = ethers.parseEther("1.0");
const Lock = await ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
expect(await lock.unlockTime()).to.equal(unlockTime);
});
});
C.3 Foundry Installation and Setup
Foundry is a blazing-fast Solidity development toolkit written in Rust. It is the preferred choice for advanced development, fuzzing, gas optimization, and Solidity-native testing (tests written in Solidity rather than JavaScript).
Installation
# Install Foundryup (the Foundry installer)
curl -L https://foundry.paradigm.xyz | bash
# Restart your terminal, then install Foundry
foundryup
On Windows, use WSL (Windows Subsystem for Linux) or Git Bash:
curl -L https://foundry.paradigm.xyz | bash
source ~/.bashrc
foundryup
Verify installation:
forge --version # forge 0.2.x
cast --version # cast 0.2.x
anvil --version # anvil 0.2.x
Foundry provides three core tools:
| Tool | Purpose |
|---|---|
forge |
Compile, test, deploy, and debug contracts |
cast |
Command-line Ethereum RPC client and utility |
anvil |
Local Ethereum node (alternative to Hardhat Network) |
Creating a Foundry Project
forge init my-foundry-project
cd my-foundry-project
Project structure:
my-foundry-project/
src/ # Solidity source files
test/ # Solidity test files
script/ # Deployment scripts
lib/ # Dependencies (git submodules)
foundry.toml # Configuration
Configuration
Edit foundry.toml:
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.24"
optimizer = true
optimizer_runs = 200
[rpc_endpoints]
sepolia = "${SEPOLIA_RPC_URL}"
[etherscan]
sepolia = { key = "${ETHERSCAN_API_KEY}" }
Installing Dependencies
Foundry uses git submodules instead of npm:
# Install OpenZeppelin contracts
forge install OpenZeppelin/openzeppelin-contracts
# Install Solmate (gas-optimized alternatives)
forge install transmissions11/solmate
# Update remappings
forge remappings > remappings.txt
Basic Workflow
# Compile
forge build
# Run tests
forge test
# Run tests with verbosity (show traces)
forge test -vvv
# Run a specific test
forge test --match-test testTransfer
# Gas report
forge test --gas-report
# Fuzz testing (Foundry runs 256 iterations by default)
forge test --fuzz-runs 10000
# Start local node
anvil
# Deploy to Sepolia
forge script script/Deploy.s.sol --rpc-url sepolia --broadcast --verify
Writing a Foundry Test
// test/Counter.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "forge-std/Test.sol";
import "../src/Counter.sol";
contract CounterTest is Test {
Counter public counter;
function setUp() public {
counter = new Counter();
counter.setNumber(0);
}
function test_Increment() public {
counter.increment();
assertEq(counter.number(), 1);
}
function testFuzz_SetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}
}
C.4 Remix IDE (Browser-Based Alternative)
Remix is a browser-based IDE ideal for quick prototyping, learning, and when you cannot install local tools. Access it at remix.ethereum.org.
Key Features
| Feature | Description |
|---|---|
| File Explorer | Create, import, and manage Solidity files |
| Compiler | Select Solidity version, enable optimization, view ABI and bytecode |
| Deploy & Run | Deploy to JavaScript VM (local), injected provider (MetaMask), or custom RPC |
| Debugger | Step-by-step transaction debugging with storage and memory inspection |
| Static Analysis | Automated security and style checks |
| Plugin System | Extend with additional tools (Etherscan verification, unit testing, etc.) |
Workflow for Textbook Exercises
- Navigate to remix.ethereum.org.
- In the File Explorer, create a new file under
contracts/(e.g.,MyToken.sol). - Write or paste the Solidity code from the textbook exercise.
- Switch to the Solidity Compiler tab. Select compiler version
0.8.24. Click Compile. - Switch to the Deploy & Run Transactions tab.
- For local testing: select Remix VM (Shanghai) as the environment.
- For testnet deployment: select Injected Provider - MetaMask and connect your wallet.
- Click Deploy and interact with the deployed contract through the generated UI.
Connecting Remix to a Local Hardhat/Anvil Node
- Start a local node:
npx hardhat nodeoranvil. - In Remix, under Environment, select Custom - External HTTP Provider.
- Enter
http://127.0.0.1:8545. - You now have access to pre-funded test accounts.
When to Use Remix vs. Hardhat/Foundry: Use Remix for quick experiments, single-file exercises, and when you are away from your development machine. Use Hardhat or Foundry for multi-file projects, automated testing, deployment pipelines, and any production work.
C.5 Testnet Configuration (Sepolia)
Sepolia is Ethereum's primary testnet for application development. It uses Proof of Stake consensus and closely mirrors mainnet behavior.
Adding Sepolia to MetaMask
MetaMask includes Sepolia by default. To enable it:
- Open MetaMask and click the network dropdown at the top.
- Toggle "Show test networks" in Settings > Advanced.
- Select "Sepolia test network."
Manual RPC Configuration
If Sepolia is not listed, add it manually:
| Parameter | Value |
|---|---|
| Network Name | Sepolia |
| RPC URL | https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY |
| Chain ID | 11155111 |
| Currency Symbol | SepoliaETH |
| Block Explorer | https://sepolia.etherscan.io |
C.6 Getting Test ETH from Faucets
Testnet ETH has no real value but is required to pay gas fees on testnets. Faucets distribute small amounts for free.
Active Sepolia Faucets (as of 2025)
| Faucet | URL | Requirements |
|---|---|---|
| Alchemy Sepolia Faucet | sepoliafaucet.com | Alchemy account |
| Infura Sepolia Faucet | infura.io/faucet/sepolia | Infura account |
| Google Cloud Web3 Faucet | cloud.google.com/application/web3/faucet | Google account |
| Chainlink Faucet | faucets.chain.link | Wallet connection |
Using cast (Foundry) to Check Balance
cast balance 0xYourAddress --rpc-url https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY
Tip
If faucets are rate-limited or dry, you can request testnet ETH from classmates or use a PoW faucet that requires mining a small amount of work in exchange for a larger drip.
C.7 Contract Verification on Etherscan
Verifying a contract on Etherscan publishes its source code, making it readable and auditable by anyone. Verified contracts display a green checkmark and enable direct interaction through Etherscan's Read/Write Contract tabs.
Verification with Hardhat
npx hardhat verify --network sepolia DEPLOYED_CONTRACT_ADDRESS "constructor_arg_1" "constructor_arg_2"
For contracts deployed with Hardhat Ignition, verification is handled automatically if hardhat-verify is configured.
Verification with Foundry
forge verify-contract \
DEPLOYED_CONTRACT_ADDRESS \
src/MyContract.sol:MyContract \
--etherscan-api-key $ETHERSCAN_API_KEY \
--rpc-url $SEPOLIA_RPC_URL \
--constructor-args $(cast abi-encode "constructor(uint256,string)" 42 "hello")
Or, if you deployed with forge script and used the --verify flag, verification happens automatically.
Verification with Remix
- Deploy your contract via Remix.
- Go to the Plugin Manager and activate the Etherscan - Contract Verification plugin.
- Enter your Etherscan API key.
- Select the contract, paste the deployed address, and click Verify.
Troubleshooting Verification Failures
| Issue | Solution |
|---|---|
| Compiler version mismatch | Ensure the exact same Solidity version and optimization settings |
| Constructor arguments wrong | Use cast abi-encode to get the exact encoding |
| Library not linked | Provide library addresses with --libraries flag |
| Already verified | The contract was previously verified; no action needed |
| Source uses imports | Flatten with forge flatten or npx hardhat flatten before manual verification |
C.8 Recommended VS Code Extensions
Visual Studio Code is the most popular editor for Solidity development. The following extensions significantly improve the development experience.
Essential Extensions
| Extension | Publisher | Purpose |
|---|---|---|
| Solidity | Juan Blanco | Syntax highlighting, compilation, linting, code completion for .sol files |
| Hardhat Solidity | Nomic Foundation | Hardhat integration, inline error diagnostics, go-to-definition, code actions |
| Even Better TOML | tamasfe | Syntax highlighting for foundry.toml |
| ESLint | Microsoft | JavaScript/TypeScript linting for Hardhat scripts and tests |
Recommended Additional Extensions
| Extension | Purpose |
|---|---|
| Solidity Visual Developer | Security-focused analysis, inheritance graphs, function call graphs |
| GitLens | Enhanced git history and blame annotations |
| Error Lens | Inline error/warning display |
| REST Client | Test RPC calls directly from VS Code |
VS Code Settings for Solidity
Add to your .vscode/settings.json:
{
"solidity.compileUsingRemoteVersion": "v0.8.24",
"solidity.defaultCompiler": "localNodeModule",
"solidity.formatter": "forge",
"editor.formatOnSave": true,
"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity",
"editor.tabSize": 4
},
"solidity.packageDefaultDependenciesContractsDirectory": "src",
"solidity.packageDefaultDependenciesDirectory": "lib"
}
Choosing Between Solidity Extensions
The Juan Blanco Solidity extension and Nomic Foundation Hardhat Solidity extension can conflict. Use one or the other:
- If using Hardhat: prefer the Nomic Foundation extension (better Hardhat integration, more accurate diagnostics).
- If using Foundry: prefer the Juan Blanco extension (supports Foundry remappings and project structure).
- Disable the one you are not using to avoid diagnostic conflicts.
C.9 Quick Command Reference
Hardhat Commands
| Command | Description |
|---|---|
npx hardhat compile |
Compile all contracts |
npx hardhat test |
Run all tests |
npx hardhat test --grep "transfer" |
Run tests matching pattern |
npx hardhat node |
Start local blockchain |
npx hardhat console --network sepolia |
Interactive console |
npx hardhat clean |
Clear build artifacts |
npx hardhat coverage |
Generate code coverage report |
Foundry Commands
| Command | Description |
|---|---|
forge build |
Compile all contracts |
forge test |
Run all tests |
forge test -vvvv |
Run tests with full traces |
forge test --gas-report |
Test with gas profiling |
forge fmt |
Format Solidity source files |
forge snapshot |
Generate gas snapshot |
anvil |
Start local blockchain node |
cast call <addr> "balanceOf(address)" <arg> |
Read contract state |
cast send <addr> "transfer(address,uint256)" <args> |
Write transaction |
With Hardhat, Foundry, and Remix configured, you have a professional Solidity development environment. Chapters 12 through 26 provide progressive exercises that build fluency with these tools.