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

  1. Download the LTS installer from nodejs.org.
  2. Run the installer with default settings (ensure "Add to PATH" is selected).
  3. 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

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_KEY should be a testnet-only account with no mainnet funds. Never store a mainnet private key in a .env file. Add .env to .gitignore immediately.

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

  1. Navigate to remix.ethereum.org.
  2. In the File Explorer, create a new file under contracts/ (e.g., MyToken.sol).
  3. Write or paste the Solidity code from the textbook exercise.
  4. Switch to the Solidity Compiler tab. Select compiler version 0.8.24. Click Compile.
  5. Switch to the Deploy & Run Transactions tab.
  6. For local testing: select Remix VM (Shanghai) as the environment.
  7. For testnet deployment: select Injected Provider - MetaMask and connect your wallet.
  8. Click Deploy and interact with the deployed contract through the generated UI.

Connecting Remix to a Local Hardhat/Anvil Node

  1. Start a local node: npx hardhat node or anvil.
  2. In Remix, under Environment, select Custom - External HTTP Provider.
  3. Enter http://127.0.0.1:8545.
  4. 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:

  1. Open MetaMask and click the network dropdown at the top.
  2. Toggle "Show test networks" in Settings > Advanced.
  3. 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

  1. Deploy your contract via Remix.
  2. Go to the Plugin Manager and activate the Etherscan - Contract Verification plugin.
  3. Enter your Etherscan API key.
  4. 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

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
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.