从零开始,在以太坊上构建软件的完整指南

网络 阅读: 2026-02-27 10:57:54

以太坊作为全球第二大区块链平台,不仅是一种加密货币,更是一个去中心化的“世界计算机”,允许开发者构建和部署无需信任、透明且抗审查的应用程序(Dapps),在以太坊上做软件,本质上是利用区块链的智能合约、去中心化存储和共识机制,创造具有自主运行、数据不可篡改特性的应用,本文将从技术栈、开发流程、关键工具到实战步骤,为你详解如何在以太坊上构建软件。

理解以太坊软件的核心:智能合约与DApp架构

在以太坊上,软件的核心是智能合约——一段部署在区块链上、自动执行的代码,它定义了应用的逻辑和规则(如资产转移、数据存储、权限管理等),而完整的“以太坊软件”通常是一个去中心化应用(DApp),由三部分组成:

  1. 智能合约(后端):运行在以太坊虚拟机(EVM)上,处理业务逻辑(如用户注册、交易结算)。
  2. 前端界面:用户与DApp交互的窗口(如网页、移动App),通过Web3.js或ethers.js与合约通信。
  3. 去中心化存储(可选):链上存储成本高,大文件(图片、视频)通常存储在IPFS、Arweave等去中心化网络,链上仅存储指针。

开发前准备:环境搭建与工具选择

开发环境

  • 钱包:MetaMask(浏览器插件钱包,用于测试和主网交互,管理私钥和 gas)。
  • 测试网络:以太坊主网gas费用高,开发时需使用测试网(如Sepolia、Goerli),通过水龙头(如Alchemy Faucet、Infura Faucet)获取测试代币。
  • IDEHardhat(推荐,支持编译、测试、调试,插件丰富)或Truffle(老牌框架,适合初学者);也可用VS Code Solidity插件编写合约。

关键工具

  • 编程语言Solidity(以太坊智能合约的主流语言,类似JavaScript,语法清晰,生态完善)。
  • 框架
    • Hardhat:本地测试节点模拟、自动化测试、部署脚本。
    • Truffle:开发框架,内置编译、测试、部署流程,适合快速原型。
  • 通信库ethers.js(轻量级,功能强大,推荐)或Web3.js(老牌库,社区成熟),用于前端与以太坊节点交互。
  • 节点服务AlchemyInfura(提供RPC节点接口,无需自己运行全节点,连接测试网/主网)。

开发流程:从合约编写到DApp上线

步骤1:设计智能合约逻辑

根据需求确定合约功能(如代币发行、NFT铸造、投票系统等),以“简单投票DApp”为例,合约需包含:

  • 候选人列表存储;
  • 用户投票功能(每人一票);
  • 投票结果查询。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract SimpleVoting {
    mapping(address => bool) public hasVoted;
    mapping(string => uint256) public voteCount;
    string[] public candidates;
    constructor(string[] memory _candidates) {
        candidates = _candidates;
    }
    function vote(string memory candidate) public {
        require(!hasVoted[msg.sender], "You have already voted.");
        bool isValid = false;
        for (uint i = 0; i < candidates.length; i  ) {
            if (keccak256(bytes(candidates[i])) == keccak256(bytes(candidate))) {
                isValid = true;
                break;
            }
        }
        require(isValid, "Invalid candidate.");
        hasVoted[msg.sender] = true;
        voteCount[candidate]  ;
    }
    function getVoteCount(string memory candidate) public view returns (uint256) {
        return voteCount[candidate];
    }
}

步骤2:编译与测试合约

使用Hardhat编译Solidity代码:

npx hardhat compile

编译后会生成artifacts目录,包含合约的ABI(应用二进制接口,定义合约函数签名)和字节码(部署到EVM的机器码)。

测试:编写测试脚本(如JavaScript/TypeScript),模拟用户交互,验证合约逻辑,Hardhat内置Mocha测试框架,示例:

const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("SimpleVoting", function () {
    it("Should allow voting and count correctly", async function () {
        const [owner, addr1] = await ethers.getSigners();
        const candidates = ["Alice", "Bob"];
        const Voting = await ethers.getContractFactory("SimpleVoting");
        const voting = await Voting.deploy(candidates);
        await voting.waitForDeployment();
        await voting.connect(addr1).vote("Alice");
        expect(await voting.getVoteCount("Alice")).to.equal(1);
        expect(await voting.hasVoted(addr1.address)).to.equal(true);
    });
});

运行测试:npx hardhat test

步骤3:部署合约到以太坊网络

部署前需配置网络(在hardhat.config.js中添加测试网/主网RPC和私钥):

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.20",
  networks: {
    sepolia: {
      url: process.env.SEPOLIA_RPC_URL,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
};

编写部署脚本(如scripts/deploy.js):

async function main() {
  const [deployer] = await ethers.getSigners();
  console.log("Deploying contracts with the account:", deployer.address);
  const candidates = ["Alice", "Bob"];
  const Voting = await ethers.getContractFactory("SimpleVoting");
  const voting = await Voting.deploy(candidates);
  await voting.waitForDeployment();
  console.log("Voting contract deployed to:", voting.target);
}
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

部署到测试网:

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

部署成功后,合约地址会显示在控制台,可通过Etherscan查看合约详情。

步骤4:开发前端界面

前端通过ethers.js与已部署的合约交互,示例React代码:

import { useState, useEffect } from "react";
import { ethers } from "ethers";
import votingContract from "./contracts/SimpleVoting.json"; // 导入ABI
function App() {
  const [contract, setContract] = useState(null);
  const [account, setAccount] = useState("");
  const [candidates, setCandidates] = useState(["Alice", "Bob"]);
  const [votes, setVotes] = useState({});
  // 连接MetaMask和初始化合约
  useEffect(() => {
    const connectWallet = async () => {
      if (window.ethereum) {
        const accounts = await window.ethereum.request({ method: "eth_requestAccounts" });
        setAccount(accounts[0]);
        const provider = new ethers.BrowserProvider(window.ethereum);
        const signer = await provider.getSigner();
        const votingContractInstance = new ethers.Contract(
          "0x...合约地址", // 替换为实际部署地址
          votingContract.abi,
          signer
        );
        setContract(votingContractInstance);
      }
    };
    connectWallet();
  }, []);
  // 投票函数
  const handleVote = async (candidate) => {
    if (contract) {
      try {
        const tx = await contract.vote(candidate);
        await tx.wait();
        alert("投票成功!");
        // 更新投票数据
        const newVotes = { ...votes };
        newVotes[candidate] = (newVotes[candidate] || 0)   1;
        setVotes(newVotes);
      } catch (error) {
        console.error(error);
        alert("投票失败:"   error.message);
      }
    }
  };
  return (
    <div>
      <h1>以太坊投票DApp</h1>
      <p>当前账户: {account}</p>
      <h2>候选人</h2>
      <ul>
        {candidates.map((candidate) => (
          <li key={candidate}>
            {candidate} - 票数: {votes[candidate] || 0}
            <button onClick={() => handleVote(candidate)}>投票</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
export default App;

步骤5:部署前端与优化

本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1379540.html

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

扫一扫关注我们,了解最新精彩内容

搜索