:2026-02-24 12:21 点击:5
以太坊作为全球第二大加密货币平台,更是一个强大的去中心化应用(DApp)开发平台,它通过智能合约实现了可编程的信任,为金融、游戏、供应链、社交媒体等众多领域带来了革命性的可能,对于初学者而言,理论学习固然重要,但“以太坊基础项目实战”才是真正掌握其核心魅力的不二法门,本文将带你走完一个简单的以太坊基础项目实战流程,从环境搭建到部署交互,让你亲身体验DApp开发的乐趣与挑战。
项目实战准备:工欲善其事,必先利其器
在开始编码之前,我们需要准备好开发环境:
项目实战步骤:构建一个简单的“留言板”DApp
我们将构建一个经典的“以太坊留言板”DApp,用户可以通过这个DApp在区块链上留下自己的留言,并查看所有留言。
初始化项目与安装依赖
mkdir ethereum-message-board cd ethereum-message-board npm init -y
npm install --save-dev hardhat npm install ethers
npx hardhat
按照提示选择"Create a basic JavaScript project"(或其他你熟悉的语言),然后一路回车,Hardhat会帮你生成基本的contracts/、scripts/、test/等目录。

编写智能合约
在contracts目录下,创建一个新的Solidity文件MessageBoard.sol。
编写智能合约代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MessageBoard {
// 定义一个结构体来存储留言信息
struct Message {
address author; // 留言者地址
string content; // 留言内容
uint256 timestamp; // 留言时间戳
}
// 存储留言的数组
Message[] public messages;
// 留言事件,方便前端监听
event NewMessage(address indexed author, string content, uint256 timestamp);
// 留言函数
function leaveMessage(string memory _content) public {
require(bytes(_content).length > 0, "Message content cannot be empty");
messages.push(Message(msg.sender, _content, block.timestamp));
emit NewMessage(msg.sender, _content, block.timestamp);
}
// 获取所有留言
function getMessages() public view returns (Message[] memory) {
return messages;
}
}
这个合约定义了一个Message结构体,一个存储留言的数组messages,以及两个核心函数:leaveMessage用于用户留言,getMessages用于获取所有留言。
编译智能合约
npx hardhat compile
编译成功后,你会在artifacts/contracts/MessageBoard.sol/目录下看到编译后的ABI(应用程序二进制接口)和字节码文件,ABI是前端与智能合约交互的桥梁。
部署智能合约
在scripts目录下,创建一个部署脚本deploy.js:
const hre = require("hardhat");
async function main() {
// 获取MessageBoard合约工厂
const MessageBoard = await hre.ethers.getContractFactory("MessageBoard");
// 部署合约
const messageBoard = await MessageBoard.deploy();
// 等待部署完成
await messageBoard.deployed();
console.log("MessageBoard deployed to:", messageBoard.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
配置Hardhat网络:在hardhat.config.js中,确保默认网络是Hardhat Network(通常默认配置即可)。
运行部署脚本:
npx hardhat run scripts/deploy.js --network localhost
执行成功后,你会看到输出的合约地址,这就是我们部署到本地测试网的留言板合约地址。请务必记下这个地址,前端需要用到它。
构建前端界面
在项目根目录下,创建一个src文件夹,用于存放前端代码。
初始化React应用(可选,也可以直接用HTML/CSS/JS):
npx create-react-app frontend cd frontend npm install ethers
在frontend/src目录下,修改App.js或创建新的组件来构建界面:
import React, { useState, useEffect } from 'react';
import { ethers } from 'ethers';
import MessageBoard from '../contracts/MessageBoard.json'; // 导入编译后的ABI
function App() {
const [account, setAccount] = useState(null);
const [messageBoard, setMessageBoard] = useState(null);
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState('');
// 初始化连接
useEffect(() => {
const init = async () => {
if (window.ethereum) {
try {
// 请求账户访问
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setAccount(accounts[0]);
// 创建provider和signer
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
// 替换为你的合约部署地址
const contractAddress = "0x..."; // 这里填入你部署的合约地址
const messageBoardInstance = new ethers.Contract(contractAddress, MessageBoard.abi, signer);
setMessageBoard(messageBoardInstance);
// 获取初始留言
const initialMessages = await messageBoardInstance.getMessages();
setMessages(initialMessages);
} catch (error) {
console.error("Error connecting to MetaMask:", error);
}
} else {
alert("Please install MetaMask!");
}
};
init();
}, []);
// 留言功能
const handleLeaveMessage = async () => {
if (messageBoard && newMessage.trim() !== '') {
try {
const tx = await messageBoard.leaveMessage(newMessage);
await tx.wait(); // 等待交易确认
// 更新留言列表
const updatedMessages = await messageBoard.getMessages();
setMessages(updatedMessages);
setNewMessage('');
} catch (error) {
console.error("Error leaving message:", error);
}
}
};
return (
<div className="App">
<h1>以太坊留言板</h1>
{account ? (
<p>当前账户: {account}</p>
) : (
<p>请连接MetaMask</p>
)}
<div>
<input
type="text"
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
placeholder="输入你的留言"
/>
<button onClick={handleLeaveMessage}>留言</button>
</div>
<div>
<h2>留言列表:</h2>
<ul>
{messages.map((msg, index) => (
<li key={index}>
<strong>{msg.author}:</strong> {msg.content} <em>({new Date(msg.timestamp * 1000).toLocaleString()})
本文由用户投稿上传,若侵权请提供版权资料并联系删除!