从零开始,构建你的第一个以太坊项目,一份完整教学指南
以太坊,作为全球第二大加密货币和领先的智能合约平台,不仅仅是一种数字资产,更是一个去中心化的、可编程的世界计算机,它为开发者提供了构建去中心化应用(Dapps)的强大能力,从金融(DeFi)到游戏,从艺术品(NFT)到身份验证,其应用潜力无穷。

本指南将带领你,从一个完全的初学者开始,一步步完成一个完整的以太坊项目,我们将使用最流行和成熟的工具栈,涵盖从环境搭建、智能合约编写、前端交互到项目部署的全过程,无论你是否有编程经验,只要跟随本教程,你就能亲手打造出属于自己的第一个DApp。
第一部分:准备工作——搭建你的开发环境
在开始编码之前,我们需要安装几个核心工具,它们就像是你的“开发工具箱”。
-
Node.js 和 npm (Node Package Manager)
- 作用:JavaScript 运行环境和包管理器,我们将用它来运行代码、管理项目依赖。
- 安装:访问 Node.js 官网 下载并安装 LTS(长期支持)版本,安装完成后,打开终端(或命令提示符),输入
node -v和npm -v确认安装成功。
-
代码编辑器
- 推荐:Visual Studio Code (VS Code),它免费、强大,并拥有丰富的插件生态。
- 推荐插件:
- Solidity by Juan Blanco:提供智能合约的语法高亮、代码提示和格式化。
- Hardhat for VS Code:为 Hardhat 框架提供更好的集成体验。
- Prettier - Code formatter:保持代码风格统一。
-
MetaMask 钱包
- 作用:这是你与以太坊区块链交互的桥梁,它是一个浏览器插件钱包,用于管理你的账户、私钥,并与你的 DApp 进行连接。
- 安装:访问 MetaMask 官网,下载对应浏览器的插件,并按照提示创建一个新钱包。请务必妥善保存你的助记词,这是你资产的唯一凭证,绝不泄露给任何人!
-
测试网 ETH

- 作用:以太坊主网上的真实资产非常宝贵,不适合用于开发和测试,我们使用“测试网”,它是一个模拟的真实网络,其中的“测试ETH”没有实际价值,但可以免费获取,用于测试交易和部署。
- 获取:你可以去 faucets.chain.link 等水龙头网站,使用你的 MetaMask 钱包地址免费获取 Sepolia 测试网的 ETH。
第二部分:项目构建——从智能合约到前端交互
我们将构建一个简单的“留言板”DApp,用户可以付费在链上留下一条留言,并查看所有留言。
步骤 1:初始化项目与安装框架
我们选择 Hardhat 作为我们的开发框架,它是一个功能全面的以太坊开发环境,能让编译、测试、部署和调试变得异常简单。
-
创建一个项目文件夹并进入:

mkdir eth-message-board cd eth-message-board
-
初始化 npm 项目:
npm init -y
-
安装 Hardhat:
npm install --save-dev hardhat
-
初始化 Hardhat 项目:
npx hardhat
在交互式提示中,选择 "Create a JavaScript project",然后一路回车接受默认配置,这会创建一个包含
contracts/,scripts/,test/等标准目录结构。
步骤 2:编写智能合约
智能合约是以太坊应用的“后端逻辑”,它运行在区块链上。
- 打开
contracts/目录,删除Lock.sol,然后创建一个新文件MessageBoard.sol。 - 编写以下代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// 导入 OpenZeppelin 的合约,以获得更安全的实现
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/**MessageBoard
* @dev 一个简单的留言板合约,允许用户支付费用来存储消息。
*/
contract MessageBoard {
// 定义一个结构体来存储留言信息
struct Message {
address author; // 留言作者地址
string content; // 留言内容
uint256 timestamp; // 留言时间戳
}
// 定义一个事件,用于在前端监听新留言
event NewMessage(address indexed author, string content, uint256 timestamp);
// 存储所有留言的数组
Message[] public messages;
// 定义留言费用(单位:wei,1 ETH = 10^18 wei)
uint256 public constant MESSAGE_FEE = 1 ether;
/**
* @dev 提交一条新留言
* @param _content 要提交的留言内容
*/
function postMessage(string memory _content) public payable {
// 确保用户支付了正确的费用
require(msg.value == MESSAGE_FEE, "Incorrect message fee!");
// 创建一个新的留言对象,并添加到数组中
messages.push(Message({
author: msg.sender,
content: _content,
timestamp: block.timestamp
}));
// 触发事件,通知前端
emit NewMessage(msg.sender, _content, block.timestamp);
}
/**
* @dev 获取所有留言的数量
*/
function getMessagesCount() public view returns (uint256) {
return messages.length;
}
/**
* @dev 获取指定索引的留言
*/
function getMessage(uint256 index) public view returns (address, string memory, uint256) {
require(index < messages.length, "Message index out of bounds");
Message storage message = messages[index];
return (message.author, message.content, message.timestamp);
}
}
代码解释:
- 我们定义了一个
Message结构体来存储每条留言的作者、内容和时间。 postMessage函数是核心功能,它要求用户支付MESSAGE_FEE(1个测试ETH),然后将新留言存入数组,并触发NewMessage事件。getMessage和getMessagesCount是“查看”函数,它们不修改链上状态,因此成本很低,可以随时被调用。
步骤 3:编译与测试
-
安装依赖:我们需要 OpenZeppelin 的合约库来保证代码安全。
npm install @openzeppelin/contracts
-
编译合约:在终端运行:
npx hardhat compile
成功后,你会在
artifacts/目录下看到编译好的合约字节码。 -
编写测试:在
test/目录下创建messageBoard.test.js,编写测试用例来确保我们的合约按预期工作。
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("MessageBoard", function () {
let MessageBoard;
let messageBoard;
let owner;
let addr1;
beforeEach(async function () {
// 在每个测试前部署新的合约实例
[owner, addr1] = await ethers.getSigners();
MessageBoard = await ethers.getContractFactory("MessageBoard");
messageBoard = await MessageBoard.deploy();
await messageBoard.waitForDeployment();
});
it("Should post a message and emit an event", async function () {
const messageContent = "Hello, Ethereum!";
const fee = ethers.parseEther("1"); // 1 ETH in wei
// 监听事件
await expect(messageBoard.connect(addr1).postMessage(messageContent, { value: fee }))
.to.emit(messageBoard, "NewMessage")
.withArgs(addr1.address, messageContent, await ethers.provider.getBlock());
// 验证留言是否被正确存储
const messagesCount = await messageBoard.getMessagesCount();
expect(messagesCount).to.equal(1);
const message = await messageBoard.getMessage(0);
expect(message.author).to.equal(addr1.address);
expect(message.content).to.equal(messageContent);
});
it("Should not allow posting with incorrect fee", async function () {
const messageContent = "This should fail";
const wrongFee = ethers.parseEther("0.5"); // 支付的费用不足
await expect(
messageBoard.connect(addr1).postMessage(messageContent, { value: wrongFee })
).to.be.revertedWith("Incorrect message fee!");
});
});
- 运行测试:
npx hardhat test
本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1275405.html
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。






