从零开始构建你的第一个以太坊智能合约Demo,入门与实践指南

以太坊,作为区块链2.0的杰出代表,不仅仅是一种加密货币,更是一个去中心化的应用平台,其核心魅力在于智能合约——一种运行在以太坊虚拟机(EVM)上,能够自动执行合约条款的计算机程序,对于想要踏入区块链开发领域的新手来说,亲手编写并部署一个以太坊智能合约Demo,是理解其工作原理的最佳途径,本文将带你一步步完成这个过程。

什么是智能合约?

智能合约是一种“那么”(If-This-Then-That)式的自动化协议,它被部署在区块链上,一旦预设的条件被触发,合约就会自动执行约定的操作,且整个过程透明、不可篡改,以太坊智能合约通常使用Solidity语言编写。

为何需要一个Demo?

一个Demo(演示程序)能够将抽象的概念具体化,通过构建一个简单的Demo,你可以:

  1. 理解核心概念:如账户、地址、余额、交易、Gas等。
  2. 熟悉开发流程:从环境搭建、合约编写、编译、部署到与合约交互。
  3. 获得实践经验:理论知识结合动手实践,印象更深刻。
  4. 建立开发信心:完成第一个Demo后,你将有能力探索更复杂的智能合约应用。

我们的Demo目标:一个简单的“投票”合约

为了演示智能合约的基本功能,我们将创建一个简单的投票合约,这个合约将允许:

  • 创建者(合约部署者)添加多个投票选项。
  • 地址(每个地址限一次)可以对其中一个选项进行投票。
  • 查询各选项的当前得票数。

构建Demo前的准备:开发环境搭建

在开始编写合约之前,你需要准备以下工具和环境:

  1. MetaMask钱包:一个浏览器插件钱包,用于管理你的以太坊账户、私钥,并与以太坊网络交互,从MetaMask官网下载并安装,创建一个新钱包并妥善保存助记词。
  2. 以太坊测试网ETH:为了在测试网络上部署和交互合约,你需要免费的测试网ETH,你可以从水龙头(Faucet)网站获取,如Sepolia测试网的Faucet。
  3. VS Code:一个流行的代码编辑器,建议安装Solidity插件,它提供语法高亮、代码提示等功能。
  4. Hardhat:一个流行的以太坊开发环境,用于编译、测试、部署智能合约,它提供了强大的插件系统和调试功能。
    • 安装Node.js和npm(或yarn)。
    • 在终端中运行 npx hardhat 初始化一个新的Hardhat项目。

编写智能合约(Solidity)

在Hardhat项目中,你会在 contracts/ 目录下找到 Lock.sol 文件(默认模板),我们可以将其重命名并修改为 Voting.sol,然后编写如下代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Voting {
    // 定义一个投票选项的结构体
    struct Candidate {
        string name;
        uint256 voteCount;
    }
    // 存储投票选项的映射,选项名称到Candidate结构体
    mapping(string => Candidate) public candidates;
    // 存储地址是否已投票的映射,防止重复投票
    mapping(address => bool) public hasVoted;
    // 投票选项的数组
    string[] public candidateNames;
    // 构造函数,在部署合约时调用,用于初始化投票选项
    constructor(string[] memory _candidateNames) {
        candidateNames = _candidateNames;
        for (uint i = 0; i < _candidateNames.length; i++) {
            candidates[_candidateNames[i]] = Candidate({
                name: _candidateNames[i],
                voteCount: 0
            });
        }
    }
    // 投票函数
    function vote(string memory candidateName) public {
        // 检查投票者是否已经投过票
        require(!hasVoted[msg.sender], "You have already voted.");
        // 检查候选选项是否存在
        require(bytes(candidates[candidateName].name).length > 0, "Candidate does not exist.");
        // 记录投票
        hasVoted[msg.sender] = true;
        candidates[candidateName].voteCount += 1;
    }
    // 获取候选人的得票数
    function getVoteCount(string memory candidateName) public view returns (uint256) {
        return candidates[candidateName].voteCount;
    }
    // 获取所有候选人的名称
    function getCandidateNames() public view returns (string[] memory) {
        return candidateNames;
    }
}

代码解释:

  • SPDX-License-Identifierpragma solidity:Solidity合约的标准头部信息,指定许可证和编译器版本。
  • contract Voting:定义了一个名为 Voting 的智能合约。
  • struct Candidate:定义了候选人结构体,包含名字和得票数。
  • mapping(string => Candidate) public candidates:一个映射,通过选项名称快速找到对应的候选人信息,并设为 public 以便区块链浏览器访问。
  • mapping(address => bool) public hasVoted:记录每个地址是否已投票。
  • string[] public candidateNames:存储所有候选选项名称的数组。
  • constructor:合约部署时执行的构造函数,用于初始化候选人列表。
  • vote(string memory candidateName):核心投票函数,包含权限检查(是否已投票、候选人是否存在),然后更新投票状态和得票数。
  • getVoteCountgetCandidateNames:查询函数,分别获取特定候选人的得票数和所有候选人名称。

编译与部署合约

  1. 编译合约: 在Hardhat项目根目录的终端中运行:

    npx hardhat compile

    如果成功,你会在 artifacts/contracts/ 目录下看到编译后的合约文件(如 Voting.json)。

  2. 编写部署脚本: 在 scripts/ 目录下,创建一个新的部署脚本,deploy.js

    async function main() {
      // 获取合约工厂
      const Voting = await ethers.getContractFactory("Voting");
      // 部署合约,这里我们传入几个候选人名称作为示例
      const candidateNames = ["Alice", "Bob", "Charlie"];
      const voting = await Voting.deploy(candidateNames);
      // 等待合约部署完成
      await voting.deployed();
      console.log("Voting contract deployed to:", voting.address);
    }
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
  3. 配置网络: 在 hardhat.config.js 文件中,你需要配置你想要部署到的测试网(如Sepolia),你需要安装 @nomicfoundation/hardhat-toolbox 插件,并配置你的MetaMask私钥(注意:不要将私钥提交到代码仓库,建议使用环境变量)。

    require("@nomicfoundation/hardhat-toolbox");
    require
    随机配图
    ('dotenv').config(); // 引入dotenv包来管理环境变量 /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.20", networks: { sepolia: { url: process.env.SEPOLIA_URL, // 从.env文件中获取 accounts: [process.env.PRIVATE_KEY] // 从.env文件中获取 } }, etherscan: { apiKey: process.env.ETHERSCAN_API_KEY // 可选,用于验证合约 } };

    创建 .env 文件,并添加你的测试网RPC URL(可以从Alchemy或Infura获取)和MetaMask私钥。

  4. 部署合约: 确保你的MetaMask钱包连接到了正确的测试网(如Sepolia Test Network),并且有足够的测试ETH。 在终端中运行部署脚本:

    npx hardhat run scripts/deploy.js --network sepolia

    部署成功后,终端会输出合约的地址,复制这个地址,你可以在以太坊测试网浏览器(如 Sepolia Etherscan)上查看你的合约。

与智能合约交互

  1. 使用Ethers.js: 你可以编写一个简单的Node.js脚本或前端应用(如使用React + Ethers.js)来调用合约的方法。 创建一个 interact.js 脚本:

    const hre = require("hardhat");
    async function main() {
      // 替换为你的合约地址
      const contractAddress = "YOUR_CONTRACT_ADDRESS_HERE";
      // 获取合约实例
      const Voting = await hre.ethers.getContractFactory("Voting");
      const voting = await Voting.attach

本文由用户投稿上传,若侵权请提供版权资料并联系删除!