从零开始,以太坊智能合约开发实例详解
以太坊作为全球领先的区块链平台,其核心魅力在于智能合约——一种运行在区块链上、自动执行合约条款的计算机程序,它允许开发者在去中心化的环境中构建各种应用,如去中心化金融(DeFi)、非同质化代币(NFT)、去中心化自治组织(DAO)等,本文将通过一个简单而实用的实例,带您一步步了解以太坊智能合约的开发流程。
开发环境准备
在开始编写智能合约之前,我们需要准备以下开发环境:
- Node.js 和 npm:JavaScript 运行时环境和包管理器,从 Node.js 官网 下载并安装 LTS 版本。
- Truffle Suite:一套流行的以太坊开发框架,包括 Truffle(开发环境、测试框架和构建工具)、Ganache(个人区块链,用于本地测试)和 Drizzle(与前端交互的库)。
- 安装:
npm install -g truffle
- 安装:
- MetaMask:一款浏览器插件钱包,用于与以太坊网络交互(测试网和主网),从 MetaMask 官网 下载并安装。
- 代码编辑器:如 VS Code,并安装 Solidity 插件以提供语法高亮和智能提示。
智能合约实例:一个简单的投票合约

我们将开发一个简单的投票合约,允许创建投票提案,并对提案进行投票,合约功能包括:
- 创建者可以创建新的投票提案。
- 地址可以投票,且每个地址只能投一次票。
- 查询提案的描述、得票数以及投票状态。
创建项目结构
- 创建一个新的项目文件夹,
voting-dapp。 - 在终端中进入该文件夹,并初始化 Truffle 项目:
truffle init
这会创建以下标准目录结构:
contracts/:存放 Solidity 智能合约文件。migrations/:存放部署脚本文件。test/:存放测试脚本文件。truffle-config.js:Truffle 配置文件。
编写智能合约
- 在
contracts目录下创建一个新的 Solidity 文件,命名为Voting.sol。 - 编写合约代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
// 定义提案结构体
struct Proposal {
string description; // 描述
uint voteCount; // 得票数
}
// 存储提案的映射,键为提案名称,值为 Proposal 结构体
mapping(string => Proposal) public proposals;
// 存储已投票地址的集合,防止重复投票
mapping(address => bool) public voters;
// 提案名称数组
string[] public proposalNames;
// 投票是否已结束
bool public votingEnded;
// 事件:当新提案创建时触发
event ProposalCreated(string proposalName);
// 事件:当有人投票时触发
event Voted(address voter, string proposalName);
// 创建提案的函数,仅限合约创建者调用
function createProposal(string memory _proposalName) public {
require(!votingEnded, "Voting has ended");
require(bytes(proposals[_proposalName].description).length == 0, "Proposal already exists");
proposals[_proposalName] = Proposal({
description: _proposalName,
voteCount: 0
});
proposalNames.push(_proposalName);
emit ProposalCreated(_proposalName);
}
// 投票函数
function vote(string memory _proposalName) public {
require(!votingEnded, "Voting has ended");
require(bytes(proposals[_proposalName].description).length != 0, "Proposal does not exist");
require(!voters[msg.sender], "You have already voted");
voters[msg.sender] = true;
proposals[_proposalName].voteCount ;
emit Voted(msg.sender, _proposalName);
}
// 结束投票函数,仅限合约创建者调用
function endVoting() public {
// 在实际应用中,可能需要添加更复杂的权限控制,比如只有特定角色可以结束投票
// 这里为了简化,假设任何调用者都可以结束,或者可以添加一个owner变量
require(!votingEnded, "Voting has already ended");
votingEnded = true;
}
// 重新开始投票函数(可选)
function restartVoting() public {
// 同样,这里简化权限控制
require(votingEnded, "Voting has not ended yet");
for (uint i = 0; i < proposalNames.length; i ) {
proposals[proposalNames[i]].voteCount = 0;
}
delete voters;
votingEnded = false;
}
// 获取所有提案名称
function getProposalNames() public view returns (string[] memory) {
return proposalNames;
}
// 获取特定提案的得票数
function getVoteCount(string memory _proposalName) public view returns (uint) {
return proposals[_proposalName].voteCount;
}
}
代码解释:

SPDX-License-Identifier和pragma solidity:Solidity 合约的标准开头,指定许可证和编译器版本。struct Proposal:定义提案的数据结构,包含描述和得票数。mapping(string => Proposal) public proposals:一个映射,用于通过提案名称快速查找提案信息。mapping(address => bool) public voters:一个映射,记录地址是否已投票,防止重复投票。string[] public proposalNames:存储所有提案名称的数组,方便遍历。bool public votingEnded:标记投票是否结束。event:定义事件,用于前端监听合约状态变化。createProposal:创建新提案,要求投票未结束且提案名称唯一。vote:为指定提案投票,要求投票未结束、提案存在且当前地址未投票。endVoting:结束投票,设置votingEnded为true。restartVoting(可选):重新开始投票,重置所有票数和投票记录。getProposalNames和getVoteCount:视图函数,用于查询提案信息,不消耗 gas。
编写部署脚本 (Migration Script)
Truffle 使用 migrations 目录下的脚本来部署合约。
- 在
migrations目录下创建一个新的文件,命名为2_deploy_voting.js(数字前缀表示部署顺序)。
const Voting = artifacts.require("Voting");
module.exports = function(deployer) {
// 部署 Voting 合约
deployer.deploy(Voting);
};
编译与测试
-
编译合约: 在终端中运行:
truffle compile
如果成功,
build/contracts目录下会生成Voting.json文件,这是合约的 ABI(应用程序二进制接口)和字节码。
-
本地测试:
- 启动 Ganache:打开 Ganache,选择 "QUICKSTART"(它会创建一个本地区块链,并提供 10 个测试账户,每个账户有 100 个 ETH)。
- 配置 Truffle:打开
truffle-config.js,确保networks部分配置了 Ganache 的网络信息(默认情况下,Ganache 监听HTTP://127.0.0.1:7545,端口可能需要根据 Ganache 启动信息调整)。// 示例配置,确保与 Ganache 一致 module.exports = { networks: { development: { host: "127.0.0.1", port: 7545, // Ganache 默认端口 network_id: "*", // 匹配任何网络 id }, }, compilers: { solc: { version: "0.8.0", // 必须与合约中 pragma solidity 版本匹配或兼容 }, }, }; - 运行迁移脚本:
truffle migrate --network development
这会执行
migrations目录下的脚本,将合约部署到 Ganache 创建的本地区块链上,成功后,终端会显示合约的部署地址。
与合约交互
-
使用 Truffle Console:
truffle console --network development
进入控制台后,可以与部署的合约实例交互:
// 获取合约实例 let votingInstance = await Voting.deployed(); // 创建提案
本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1332848.html
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。






