.jpg)
以太坊,作为全球领先的智能合约平台,不仅加密货币的基石,更催生了去中心化应用(DApps)的蓬勃发展,对于许多开发者而言,踏入以太坊开发的世界,最有效的方式莫过于通过一个具体的实例来学习,本文将以一个简单但功能完整的“投票DApp”为例,带你走过以太坊开发的核心流程,包括环境搭建、智能合约编写、测试、部署以及与前端交互的初步概念。
在开始编码之前,我们需要准备以下开发环境:
npm install -g truffle
npm install -g ganache 命令安装命令行版本。voting-dapp。mkdir voting-dapp cd voting-dapp
truffle init
这会创建以下标准目录结构:
contracts/:存放 Solidity 智能合约文件。migrations/:存放部署脚本文件。test/:存放测试文件。truffle-config.js:Truffle 配置文件。我们的投票DApp将允许创建投票,并让参与者对特定选项进行投票。
contracts 目录下创建一个新的 Solidity 文件,命名为 Voting.sol。// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
// 定义投票选项的结构体
struct Option {
string name;
uint voteCount;
}
// 定义提案的结构体
struct Proposal {
string description;
mapping(address => bool) hasVoted; // 记录用户是否已投票
Option[] options; // 投票选项数组
}
// 存储所有提案的映射,key为提案ID,value为提案
mapping(uint => Proposal) public proposals;
uint public proposalCount;
// 提案创建者
address public owner;
// 构造函数,设置合约所有者
constructor() {
owner = msg.sender;
}
// 创建新提案
function createProposal(string memory _description, string[] memory _optionNames) public {
require(msg.sender == owner, "Only owner can create proposals");
proposalCount++;
Proposal storage proposal = proposals[proposalCount];
proposal.description = _description;
for (uint i = 0; i < _optionNames.length; i++) {
proposal.options.push(Option({
name: _optionNames[i],
voteCount: 0
}));
}
}
// 对提案的某个选项进行投票
function vote(uint _proposalId, uint _optionIndex) public {
Proposal storage proposal = proposals[_proposalId];
require(!proposal.hasVoted[msg.sender], "You have already voted for this proposal");
require(_proposalId > 0 && _proposalId <= proposalCount, "Proposal does not exist");
require(_optionIndex < proposal.options.length, "Option does not exist");
proposal.hasVoted[msg.sender] = true;
proposal.options[_optionIndex].voteCount++;
}
// 获取提案的选项数量
function getProposalOptionsCount(uint _proposalId) public view returns (uint) {
return proposals[_proposalId].options.length;
}
// 获取提案的某个选项信息
function getOption(uint _proposalId, uint _optionIndex) public view returns (string memory, uint) {
return (proposals[_proposalId].options[_optionIndex].name, proposals[_proposalId].options[_optionIndex].voteCount);
}
}
合约解析:
Option 结构体:存储投票选项名称和票数。Proposal 结构体:存储提案描述、已投票用户记录和选项数组。proposals:映射,用于存储所有提案。proposalCount:提案总数,也用作新提案的ID。owner:提案创建者地址,只有合约所有者可以创建提案。createProposal:创建新提案,传入提案描述和选项名称数组。vote:对指定提案的指定选项进行投票,并确保每个地址只能投一次票。getProposalOptionsCount 和 getOption:视图函数,用于获取提案的选项信息和投票结果。为了让 Truffle 知道如何部署我们的合约,我们需要在 migrations 目录下创建一个新的迁移脚本。
migrations 目录下创建文件 2_deploy_contracts.js(数字前缀表示部署顺序)。const Voting = artifacts.require("Voting");
module.exports = function (deployer) {
// 部署 Voting 合约
// 可以在这里传入初始参数,如果构造函数有的话
// deployer.deploy(Voting, "Initial Proposal Description", ["Option1", "Option2"]);
// 但我们的合约构造函数没有参数,所以直接部署
deployer.deploy(Voting);
};
Truffle 使用 Mocha 和 Chai 进行测试,在 test 目录下创建 voting.test.js 文件:
const Voting = artifacts.require("Voting");
contract("Voting", (accounts) => {
let votingInstance;
const owner = accounts[0];
const voter1 = accounts[1];
const voter2 = accounts[2];
beforeEach(async () => {
votingInstance = await Voting.new();
});
it("should have an owner", async () => {
const contractOwner = await votingInstance.owner();
assert.equal(contractOwner, owner, "The owner is not correct");
});
it("should allow the owner to create a proposal", async () => {
const description = "What should we have for lunch?";
const optionNames = ["Pizza", "Sushi", "Burger"];
await votingInstance.createProposal(description, optionNames, { from: owner });
const proposalCount = await votingInstance.proposalCount();
assert.equal(proposalCount.toNumber(), 1, "Proposal count should be 1");
const retrievedDescription = await votingInstance.proposals(1).description;
assert.equal(retrievedDescription, description, "Proposal description is incorrect");
const optionsCount = await votingInstance.getProposalOptionsCount(1);
assert.equal(optionsCount.toNumber(), 3, "Options count is incorrect");
});
it("should allow a voter to vote", async () => {
await votingInstance.createProposal("Favorite color?", ["Red", "Blue", "Green"], { from: owner });
await votingInstance.vote(1, 0, { from: voter1 }); // 投给第一个选项 "Red"
const redVotes = await votingInstance.getOption(1, 0);
assert.equal(redVotes[1].toNumber(), 1, "Red vote count should be 1");
const hasVoted = await votingInstance.proposals(1).hasVoted(voter1);
assert.equal(hasVoted, true, "Voter should have voted");
});
it("should not allow a voter to vote twice", async () => {
await votingInstance.createProposal("Favorite color?", ["Red", "Blue", "Green"], { from: owner });
await votingInstance.vote(1, 0, { from: voter1 });
try {
await votingInstance.vote(1, 1, { from: voter1 });
assert.fail("Expected revert but none was received");
} catch (error) {
assert.include(error.message, "You have already voted for this proposal");
}
});
});
运行测试: 在项目根目录下运行:
truffle test
Truffle 会自动启动本地测试网络(如果未启动),运行测试并输出结果。
OE数字交易平台官网,开启数字资产交易新纪元,安全高效触达全球机遇 在数字经济浪潮席卷全球的今天,数字资产交易已成为投资者、企业及机构布局未来的核心赛道,作为行业领先的数字资产综合服务平台,OE数字交易平台官网([此处可插入官网链接])凭借技术创新、安全合规与全球
狗狗币与BTT,从网红 meme到存储革命的本质区别 在加密货币的浪潮中,狗狗币(DOGE)与比特流(BTT)常被一同提及,二者均起源于“老牌加密货币”的技术基础,却因定位、生态和用户群体的差异,走上了截然不同的发展道路,理解它们的区别,需从底层逻辑到应用场景逐一拆解。
1.BRETT币价格:$0.1 2.2024年10月29日 BRETT币今日行情走势0.73币价格:0.73 3.24H最高:0.73 4.24H成交额:7.41亿 5.最大发行量:100.0亿 6.24H换手:10.24% 7.24H最低:0.64 8.24H成交量:10.14亿 9.当前发行量:99.1亿 10.24H波幅:14.01% 11.历史最高:1.37 12.最大市
穿越牛熊的传奇,探寻XRP瑞波币的众筹价之谜 在波涛汹涌的加密货币海洋中,每一枚主流币种都有一段属于自己的起源故事,这些故事中,有的充满了技术极客的理想主义,有的则夹杂着争议与疑云,而XRP,作为市值长期稳居前列的数字资产,其故事的开篇,便与一个引人注目的数字—
一、数字货币钱包大全,该用哪个钱包,看完这篇就够了在储布和挖矿方面,我推荐和数硬件钱包和家佳保智能家庭矿机,产品最核心优势只有两个字:安全。以和数硬件钱包为例。和数硬件钱包优势在于:一、私钥种子层层加密物理隔绝永不触网首先,创建钱包时,生成种子密码存储在本地
一、区块链钱包如何发布商品(区块链付款流程)区块链钱包的主要功能通常一个钱包会包含以下功能:支持通过生成助记词、Keystore文件、私钥创建钱包账号。支持导出钱包账号助记词、私钥、Keystore文件。支持多个钱包账号管理账户余额查询及转账功能(二维码扫描支持)。支持ERC
欧亿交易所股票行情,洞察全球资本市场的动态风向标 在数字化金融时代,欧亿交易所凭借其多元化的产品布局和高效的交易机制,已成为全球投资者关注的重要股票行情平台,作为连接资本与企业的桥梁,欧亿交易所不仅提供实时、精准的股票数据,更通过深度市场分析,助力投资者把
1.QTUM币价格:$2.45 2.2024年11月09日 QTUM币今日行情走势17.46币价格:17.46 3.24H最高:17.46 4.24H成交额:1.11亿 5.最大发行量:1.08亿 6.24H换手:6.02% 7.24H最低:16.89 8.24H成交量:632.79万 9.当前发行量:1.08亿 10.24H波幅:3.38% 11.历史最高:714.37 12.最大
欧亿交易如何通过卖币赚佣金,实操指南与核心逻辑 在数字货币市场,“赚佣金”是许多参与者关注的盈利模式,而欧亿交易(OYEX)等平台为用户提供了“卖币赚佣金”的渠道,这一模式的核心逻辑在于:用户作为交易推广者或流动性提供者,通过引导他人交易或直接参与卖币行为,从平
欧易交易所中文版APP(暂无下载)安全合规的数字资产交易新选择 在数字资产交易领域,选择一个安全、稳定且功能全面的平台至关重要,欧易交易所(OKX)作为全球领先的加密货币交易平台,其中文版APP一直备受中国用户关注,欧易交易所中文版APP(暂无下载)及安卓最新版v6.1的
欧艺交一所最新动态,深化国际艺术教育合作,开启人才培养新篇章 欧洲艺术教育交流中心(简称“欧艺交一所”)发布最新消息,围绕国际艺术教育合作、课程体系创新、青年艺术家扶持等核心领域推出多项重要举措,引发全球艺术教育界广泛关注,作为连接欧洲与中国及全球艺术教育
狗狗币的加密方式是什么? 提到狗狗币(Dogecoin)的加密方式,首先要明确一个核心事实:狗狗币并非使用独立的加密算法,而是基于莱特币(Litecoin)的技术架构,采用Scrypt加密算法,这一选择决定了它与比特币、以太坊等加密货币在挖矿、安全性和设计理念上的显著差异。 Scr
以太坊开源钱包,开启去中心化金融的便捷之门 在区块链技术的浪潮中,以太坊作为全球第二大公有链,凭借其智能合约功能和庞大的生态系统,成为了去中心化金融(DeFi)、NFT、DAO等创新应用的温床,而以太坊钱包,作为用户与以太坊网络交互的“入口”,不仅承担着资产存储的核
以太坊的几个比,不止是速度,更是价值网络的深度较量 当人们谈论以太坊时,往往首先想到的是它作为“世界计算机”的宏大愿景,或是其作为加密货币领域第二大市值的地位,要真正理解以太坊的现在与未来,我们需要深入其内部,审视那些定义其竞争力和发展潜力的“几个比”,这
ZBT币推广模式解析,社区驱动与价值赋能的双轮策略 在数字经济蓬勃发展的今天,各类加密货币项目层出不穷,而一个成功的推广模式往往是项目从众多竞争者中脱颖而出的关键,ZBT币作为一种新兴的加密资产,其推广模式并非单一渠道的强力灌输,而是构建了一套以“社区驱动”为核心
Bybit与比特币,加密货币生态中的深度联动与创新探索 在全球加密货币市场的浪潮中,Bybit作为头部衍生品交易平台,与比特币的联动堪称行业典范,二者不仅共同见证了数字资产从极客圈走向主流的历程,更在技术迭代、生态构建与用户教育层面形成了深度协同,成为推动比特币应用价
狗狗币的第一个铭文怎么获得?新手指南与核心要点 当“狗狗币铭文”成为加密圈的热词,许多DOGE持有者开始关注:如何才能获得这个数字资产的新形态?作为狗狗币生态的创新探索,首个铭文的获取并非直接“挖矿”,而是通过特定的技术路径和参与方式实现,以下是关键步骤和注意
1.RON币价格:$1.61 2.2024年11月12日 RON币今日行情走势11.48币价格:11.48 3.24H最高:11.4 4.24H成交额:3.26亿 5.最大发行量:10.0亿 6.24H换手:7.89% 7.24H最低:10.62 8.24H成交量:2838.34万 9.当前发行量:10.0亿 10.24H波幅:7.38% 11.历史最高:31.72 12.最大市
易欧亿交易所密码重置全流程指南 在数字资产交易中,账户安全至关重要,若不慎遗忘易欧亿交易所密码,可通过官方渠道快速重置,以下是具体操作步骤及注意事项: 密码重置的官方途径 易欧亿交易所为保障用户资产安全,密码重置需通过官方指定渠道操作,避免第三方风险,目前支持
一、怎么注册以太坊钱包申请以太坊钱包官方网站。搜索进入“以太坊钱包官网”,输入密码,然后单击生成钱包;下载并保存密钥文件;您可以选择其他熟悉的方式来访问您的钱包。你的钱包完全生成好了,别人可以给你发送以太坊,或者你也可以给别人发送以太坊了。必须记住申请过程