以太坊编写教程,从零开始构建你的第一个DApp
以太坊作为全球领先的智能合约平台,不仅仅是一种加密货币,更是一个去中心化的应用(DApp)生态系统,它允许开发者通过编写智能合约,在区块链上创建各种不可篡改、自动执行的应用程序,本教程将带你从零开始,逐步了解并掌握以太坊智能合约的编写过程。
为什么选择以太坊编写智能合约?
在开始之前,我们首先要明白为什么以太坊是编写智能合约的热门选择:
- 图灵完备:以太坊的智能合约编程语言(如Solidity)支持复杂的逻辑运算,可以实现各种功能。
- 庞大的社区和生态系统:拥有全球最大的开发者社区,丰富的学习资源、工具库和框架支持(如Truffle, Hardhat, Web3.js)。
- 成熟的标准:如ERC-20(代币标准)、ERC-721(NFT标准)等,为开发者提供了构建可交互资产的基础。
- 去中心化应用平台:不仅仅是代币,更可以构建去中心化的金融(DeFi)、游戏、社交、供应链等应用。
准备工作:开发环境搭建
在开始编写智能合约之前,你需要准备以下开发环境:
-
代码编辑器:
- Visual Studio Code (VS Code):强烈推荐,配合Solidity插件(如Solidity by Juan Blanco, Hardhat for VS Code)可以获得语法高亮、代码提示、编译错误检查等强大功能。
-
Node.js 和 npm/yarn:
- 以太坊开发框架(如Truffle, Hardhat)基于Node.js,请从 Node.js官网 下载并安装LTS版本。
- npm会随Node.js一起安装,或者你也可以安装yarn(
npm install -g yarn)。
-
以太坊客户端/开发框架:
- Truffle:一个成熟的开源开发环境,测试框架和资产管理器,用于构建以太坊DApp。
- Hardhat:一个更现代、更灵活的开发环境,以其强大的调试和测试功能而受到欢迎。
- 本教程将以 Hardhat 为例进行讲解,因为它对新手相对友好且功能强大。
-
MetaMask 钱包:
- 一个浏览器扩展钱包,用于与以太坊网络交互,管理账户,签署交易,从 MetaMask官网 安装。
你的第一个智能合约:一个简单的投票合约
让我们通过编写一个简单的投票合约来入门。
-
创建Hardhat项目: 打开终端,运行以下命令:
mkdir hardhat-vote-demo cd hardhat-vote-demo npm init -y npm install --save-dev hardhat npx hardhat
在交互式界面中,选择 "Create a JavaScript project"(或其他你熟悉的语言,如TypeScript),然后一路回车使用默认配置(或根据需要修改)。
-
编写智能合约: Hardhat会创建一个
contracts目录,在此目录下创建一个新文件Vote.sol:// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; contract Vote { // 定义候选人结构体 struct Candidate { string name; uint256 voteCount; } // 存储候选人数组 Candidate[] public candidates; // 存储投票地址,防止重复投票 mapping(address => bool) public hasVoted; // 构造函数,初始化候选人 constructor(string[] memory candidateNames) { for (uint i = 0; i < candidateNames.length; i++) { candidates.push(Candidate({ name: candidateNames[i], voteCount: 0 })); } } // 投票函数 function vote(uint256 candidateIndex) public { require(!hasVoted[msg.sender], "You have already voted."); require(candidateIndex < candidates.length, "Invalid candidate index."); hasVoted[msg.sender] = true; candidates[candidateIndex].voteCount++; } // 获取候选人数量 function getCandidatesCount() public view returns (uint256) { return candidates.length; } // 获取候选人信息 function getCandidate(uint256 index) public view returns (string memory, uint256) { require(index < candidates.length, "Invalid candidate index."); return (candidates[index].name, candidates[index].voteCount); } } -
理解合约代码:
SPDX-License-Identifier和pragma solidity:许可证和Solidity版本声明。contract Vote:定义名为Vote的智能合约。struct Candidate:定义候选人结构体,包含名字和票数。Candidate[] public candidates:动态数组存储所有候选人。mapping(address => bool) public hasVoted:映射记录每个地址是否已投票。constructor:合约部署时执行的构造函数,用于初始化候选人列表。vote(uint256 candidateIndex):投票函数,检查投票资格后增加对应候选人的票数。getCandidatesCount()和getCandidate(uint256 index):视图函数,用于查询候选人数和具体候选人信息。
-
编译合约: 在终端中运
行:
npx hardhat compile
如果编译成功,Hardhat会在
artifacts目录下生成编译后的合约字节码和ABI(Application Binary Interface)。
测试你的智能合约
测试是确保智能合约正确性的关键步骤。
-
编写测试脚本: 在
test目录下创建vote.test.js文件(如果使用TypeScript,则是.ts):const { expect } = require("chai"); const { ethers } = require("hardhat"); describe("Vote Contract", function () { it("Should allow voting and tally votes correctly", async function () { // 获取签名者 const [owner, addr1, addr2] = await ethers.getSigners(); // 部署合约 const Vote = await ethers.getContractFactory("Vote"); const voteContract = await Vote.deploy(["Alice", "Bob"]); await voteContract.deployed(); // 初始票数应为0 expect(await voteContract.getCandidate(0)).to.deep.equal(["Alice", 0]); expect(await voteContract.getCandidate(1)).to.deep.equal(["Bob", 0]); // addr1投票给Alice (index 0) await voteContract.connect(addr1).vote(0); expect(await voteContract.getCandidate(0)).to.deep.equal(["Alice", 1]); expect(await voteContract.hasVoted(addr1.address)).to.equal(true); // addr2投票给Bob (index 1) await voteContract.connect(addr2).vote(1); expect(await voteContract.getCandidate(1)).to.deep.equal(["Bob", 1]); // addr1不能重复投票 await expect(voteContract.connect(addr1).vote(1)).to.be.revertedWith( "You have already voted." ); // 投票给无效候选人index应revert await expect(voteContract.connect(owner).vote(2)).to.be.revertedWith( "Invalid candidate index." ); }); }); -
运行测试: 在终端中运行:
npx hardhat test
如果所有测试通过,说明你的合约逻辑基本正确。
部署合约到测试网
为了在真实的以太坊环境中测试你的合约,你需要部署到测试网(如Ropsten, Goerli, Sepolia)。
-
获取测试ETH: 从测试网水龙头获取免费的测试ETH,例如Goerli测试网的 faucet。
-
配置Hardhat网络: 在
hardhat.config.js中添加测试网配置(以Goerli为例,你需要安装@nomicfoundation/hardhat-network和@nomicfoundation/hardhat-ethers,以及dotenv来管理环境变量):require("@nomicfoundation/hardhat-toolbox"); require("dotenv").config(); const PRIVATE_KEY = process.env.PRIVATE_KEY; const GOERLI_URL = process.env.GOERLI_URL; module.exports = { solidity: "0.8.9", networks: { goerli: { url: GOERLI_URL, accounts: [PRIVATE_KEY], }, }, };在项目根目录创建
.env文件,填入你的私钥(从MetaMask导出,注意安全!)和Goerli RPC URL(可以从 [Infura](https://
上一篇: 和安游戏厅在几楼卖游戏币
下一篇: 比特币怎么交易 比特币怎么买卖