写一份智能合约:Counter 计数器
创建一个最简单的链上程序:记录一个数字,允许用户把它加一。
这份代码会让你接触 Solidity 的基本语法、链上存储、函数调用和交易费用。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Counter {
uint256 public count;
constructor() {
count = 0;
}
function increment() public {
count += 1;
}
function decrement() public {
require(count > 0, "Count is zero");
count -= 1;
}
function reset() public {
count = 0;
}
}逐行理解
① pragma solidity ^0.8.24;
声明合约使用的 Solidity 编译器版本范围。这里要求兼容 0.8.24 及以上、低于 0.9.0 的版本。
② uint256 public count;
声明一个无符号整数变量 count,用来保存计数值。哈哈哈哈这不是c语言吗
public 会让编译器自动生成一个外部可调用的读取函数 count()。它不是让任何人都能随意修改这个变量。
③ constructor()
构造函数,在合约部署时执行一次。由于 Solidity 会将整数状态变量默认初始化为 0,这里的显式赋值其实可以省略。
④ increment()
将计数值增加 1。它会修改链上状态,因此通过钱包在真实网络调用时,通常需要发送交易并支付 Gas。
⑤ require(count > 0, "Count is zero")
检查计数值是否大于 0。如果条件不满足,执行会回退,后续状态修改不会生效。
⑥ reset()
把计数值重置为 0。注意,这里没有设置管理员权限,因此任何人都可以调用它——这是我们之后要改进的设计。
部署ETH开发环境(docker)
笔者使用mac所以希望使用docker部署会方便一些,以后可以在各平台迁移使用
您需要下载docker和homebrew在mac上这我就不介绍了!
接下来我们建立一个可迁移的 Hardhat 3 + Solidity 开发环境。代码保存在 Mac 本地,容器提供运行环境;将来迁移时,可以用同一份项目配置重建。
第 1 步:创建项目目录和 Docker 配置
mkdir -p ~/eth-learning
cd ~/eth-learning
mkdir -p contracts test scripts然后创建 compose.yaml:
cat > compose.yaml <<'EOF'
services:
dev:
image: node:22-bookworm-slim
working_dir: /workspace
command: ["sleep", "infinity"]
ports:
- "127.0.0.1:8545:8545"
volumes:
- .:/workspace #@项目源代码保存在 Mac 本地
- node_modules:/workspace/node_modules
- npm_cache:/root/.npm
init: true
volumes:
node_modules:
npm_cache:
EOF这个配置有三个重要设计:
.:/workspace:项目源代码保存在 Mac 本地。node_modules:依赖保存在 Docker 管理的独立卷中,避免把 Linux 依赖直接混入 Mac 项目目录。127.0.0.1:8545:8545:为后续本地测试链预留端口,只允许 Mac 本机访问,不直接暴露到局域网。
第 2 步:启动容器并验证 Node.js
执行:
cd ~/eth-learning
docker compose run --rm dev node --version
docker compose run --rm dev npm --version第一条命令应显示 Node.js v22.13.0 或更高的 22.x 版本,满足 Hardhat 3 的最低版本要求。
再检查容器架构:
docker compose run --rm dev node -p \
"process.platform + '/' + process.arch"预期类似:
linux/arm64这一步只是检查容器环境,不会启动区块链,也不会花费真实 ETH。
第 3 步:初始化 Hardhat 3
执行:
cd ~/eth-learning
docker compose run --rm dev npx hardhat --init如果出现交互式初始化菜单:
要保存在哪个路径直接回车
选择官方推荐的默认项目模板。A TypeScript Hardhat project using Node Test Runner and Viem
如果询问是否安装依赖,选择确认。
如果询问是否允许安装所需的软件包,确认继续。
最后问是否run选择y

Hardhat 3 官方提供 TypeScript、Solidity 测试和合约部署相关的项目模板。
报错
npm install --save-dev "hardhat@^3.19.0" "@nomicfoundation/hardhat-toolbox-viem@^5.0.7" "@nomicfoundation/hardhat-ignition@^3.1.8" "@types/node@^22.8.5" "forge-std@foundry-rs/forge-std#v1.16.2" "typescript@~6.0.3" "viem@^2.47.6"
npm error code ENOENT
npm error syscall spawn git
npm error path git
npm error errno -2
npm error enoent An unknown git error occurred
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm error A complete log of this run can be found in: /root/.npm/_logs/2026-10-12T13_03_44_317Z-debug-0.log
Error HHE1400: Failed to install the project dependencies.
Please try again. If it persists, please open an issue in the Hardhat repository.
For more info go to https://hardhat.org/HHE1400 or run Hardhat with --show-stack-traces
npm notice
npm notice New major version of npm available! 10.9.9 -> 12.2.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0
npm notice To update run: npm install -g [email protected]
npm notice
What's next:
Debug this Compose error with Gordon → docker ai "help me fix this compose error"我们之前使用的是 node:22-bookworm-slim 镜像,它是精简镜像,不保证预装 Git。
推荐的修复方式:在 Docker 镜像中安装 Git,然后重新运行依赖安装。这样仍然保留 Docker 的可迁移性,不需要在 Mac 上额外安装 Git 来满足容器内部的依赖要求。
第 1 步:给开发容器安装 Git
在 Mac 终端中,确认你当前位于 ~/eth-learning,然后执行:
cd ~/eth-learning
cat > Dockerfile <<'EOF'
FROM node:22-bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
EOF第 2 步:让 Compose 使用自己的镜像
用下面的内容替换 compose.yaml:
cat > compose.yaml <<'EOF'
services:
dev:
build:
context: .
dockerfile: Dockerfile
working_dir: /workspace
command: ["sleep", "infinity"]
ports:
- "127.0.0.1:8545:8545"
volumes:
- .:/workspace
- node_modules:/workspace/node_modules
- npm_cache:/root/.npm
init: true
volumes:
node_modules:
npm_cache:
EOF现在的区别是:
Dockerfile负责安装 Git。compose.yaml负责启动和管理开发容器。将来迁移时,只需要携带这两个文件和项目代码,就能重建相同的基础环境。
第 3 步:重新构建并检查 Git
执行:
docker compose build dev构建完成后,再执行:
docker compose run --rm dev git --version
docker compose run --rm dev node --version如果第一条显示类似 git version 2.x.x,说明问题已经解决。
重新安装初始化所需的依赖
现在 Git 已经可用,直接在 Mac 终端执行下面的命令。它会把 Hardhat 和初始化模板需要的依赖写入 package.json,并生成锁文件。
cd ~/eth-learning
docker compose run --rm dev npm install --save-dev \
"hardhat@^3.19.0" \
"@nomicfoundation/hardhat-toolbox-viem@^5.0.7" \
"@nomicfoundation/hardhat-ignition@^3.1.8" \
"@types/node@^22.8.5" \
"forge-std@foundry-rs/forge-std#v1.16.2" \
"typescript@~6.0.3" \
"viem@^2.47.6"这条命令沿用 Hardhat 初始化程序此前给出的依赖版本范围,不需要重新初始化项目。
检查安装结果
如果安装完成,再执行:
cd ~/eth-learning
docker compose run --rm dev npx hardhat --version
docker compose run --rm dev npm ls --depth=0
ls -l package.json package-lock.json预期能看到 Hardhat 版本 3.x,并且 package.json、package-lock.json 均存在。
很好,Hardhat 3 本地开发环境的依赖已经安装成功。
目前确认的状态:
Hardhat:
3.19.0Node.js:
v22.23.3TypeScript:
6.0.3Viem:
2.57.4Hardhat Ignition:
3.1.8依赖安装完成,npm 报告
0 vulnerabilities
你现在已经有了一套运行在 Docker 中的 Solidity 开发工具链,而且 package-lock.json 已经生成,后续迁移到 Ubuntu 时可以用它锁定依赖版本。
把现有项目接入 VS Code
检查 VS Code 命令是否可用
在 Mac 终端执行:
code --version如果输出版本号,继续执行:
cd ~/eth-learning
code .这会在 VS Code 中打开整个 ETH 项目。
如果提示 command not found: code,也没关系,可以先从应用程序中手动打开 VS Code,再选择 File → Open Folder,打开 ~/eth-learning。
安装 Solidity 扩展
在 VS Code 左侧点击扩展图标,搜索:
Solidity
选择一个支持 Solidity 语法高亮、代码诊断和编译器版本配置的扩展。安装后打开项目中的 .sol 文件,就能更方便地阅读和编写合约。
注意:扩展可以辅助编写代码,但实际编译和测试仍然由我们的 Hardhat 容器执行,避免本机和容器使用不同的依赖版本。

认识项目文件
打开项目后,你会看到类似这样的结构:
eth-learning/
├── contracts/ # Solidity 智能合约
├── test/ # 自动化测试
├── ignition/ # 合约部署模块
├── scripts/ # 辅助脚本
├── hardhat.config.ts # Hardhat 配置
├── package.json # 项目依赖
├── package-lock.json # 锁定依赖版本
├── Dockerfile # 开发镜像
└── compose.yaml # Docker 服务配置以后主要在 IDE 里编写 contracts/Counter.sol,然后通过 VS Code 终端或任务调用 Docker 编译、测试和部署。
在 VS Code 里运行第一次编译
在 VS Code 顶部菜单点击 Terminal → New Terminal(终端 → 新建终端),然后执行:
cd ~/eth-learning
docker compose run --rm dev npx hardhat compile这条命令的意思是:
编译器会检查合约语法,并生成编译产物。即使你在 Mac 上没有安装 Node.js 或 Solidity 编译器,这一步也可以通过 Docker 中的开发环境执行。

从输出看,Docker 和 Hardhat 已经可以正常运行,Solidity 编译器也已成功下载。 目前没有报错。
我这里已经安装好了一些拓展,你可以再安装这两个扩展


好,那我们继续把 VS Code 连接到 Docker 容器。接下来你就能在 IDE 里使用容器中的 Node.js、Hardhat 和 Solidity 开发工具。
第一步:创建 Dev Containers 配置
在 VS Code 的终端中执行下面的命令:
cd ~/eth-learning
mkdir -p .devcontainer
cat > .devcontainer/devcontainer.json <<'EOF'
{
"name": "ETH Solidity Learning",
"dockerComposeFile": "../compose.yaml",
"service": "dev",
"workspaceFolder": "/workspace",
"shutdownAction": "stopCompose",
"overrideCommand": false,
"customizations": {
"vscode": {
"extensions": [
"NomicFoundation.hardhat-solidity"
]
}
}
}
EOF这个配置会让 VS Code 使用你现有的 compose.yaml,而不是再创建一套独立的开发环境。
第二步:在容器中重新打开项目
按
Cmd + Shift + P。输入
Dev Containers: Reopen in Container。点击对应命令。
等待 VS Code 连接容器完成。
如果弹出是否信任工作区的提示,确认这是你自己创建的 eth-learning 项目后,可以选择信任。
第三步:验证环境
重新连接完成后,在 VS Code 的终端执行:记得再打开一个bash
pwd
node --version
npx hardhat --version预期结果:
工作目录:
/workspaceNode.js:
v22.xHardhat:
3.x
然后执行测试:
npx hardhat test预期仍然是 5 passing。
好了总算配置好了
马上可以学习代码了
然后配置好的结果在bash里看是这样!
root@ad7657016973:/workspace# node --version
npx hardhat --version
npx hardhat test
v22.23.3
3.19.0
No contracts to compile
Running Solidity tests
contracts/Counter.t.sol:CounterTest
✔ test_InitialValue()
✔ test_IncByZero()
✔ testFuzz_Inc(uint8) (runs: 256)
Running node:test tests
Counter
✔ Should emit the Increment event when calling the inc() function
✔ The sum of the Increment events should match the current value
5 passing (3 solidity, 2 nodejs)
root@ad7657016973:/workspace#