以太坊作为全球领先的智能合约平台,不仅仅是一种加密货币,更是一个去中心化的应用(DApp)开发平台,它允许开发者构建和运行无需信任第三方、公开透明、抗审查的应用程序,本教程将带你从零开始,逐步了解并实践如何制作一个简单的以太坊应用(DApp)。

了解基础知识:以太坊是什么?

在动手之前,我们需要对以太坊的核心概念有所了解:

  1. 区块链:以太坊是一个基于区块链技术的分布式账本,记录着网络上的所有交易和状态变更。
  2. 以太币 (ETH):以太坊网络的原生加密货币,用于支付交易费用(Gas费)和激励矿工。
  3. 智能合约 (Smart Contract):运行在以太坊区块链上的自动执行的程序代码,它们是DApp的后端逻辑,一旦部署就无法更改。
  4. 账户 (Accounts):分为外部账户(由用户私钥控制,如你的钱包)和合约账户(由智能代码控制)。
  5. 虚拟机 (EVM - Ethereum Virtual Machine):以太坊网络中执行智能合约的全球共享计算机。
  6. Gas:执行智能合约或交易时需要支付的计算费用,以防止无限循环和滥用网络资源。

开发环境搭建

开始开发前,你需要准备以下工具和环境:

  1. 代码编辑器
    • Visual Studio Code (VS Code):强烈推荐,安装其官方插件 Solidity by Juan Blanco,提供语法高亮、代码提示、编译等功能。
  2. Node.js 和 npm (Node Package Manager)
    • 访问 Node.js 官网 下载并安装 LTS (长期支持) 版本,npm 会随 Node.js 一起安装。
  3. Truffle Suite
    • Truffle:最受欢迎的以太坊开发框架之一,用于智能合约的编译、测试、部署和管理。
    • Ganache:一个个人以太坊区块链,用于快速创建和部署测试网络,你可以看到所有交易的详细信息,方便调试。
    • 安装命令:打开终端或命令提示符,运行 npm install -g truffle ganache-cli,Ganache 也有图形界面版本,可以从其官网下载。
  4. MetaMask 钱包插件
    • 浏览器插件(Chrome, Firefox, Brave 等),用于与以太坊测试网络交互,管理你的测试账户和私钥。
    • MetaMask 官网 下载并安装,创建钱包并备份好助记词!

创建你的第一个以太坊项目

  1. 初始化项目

    • 在你的电脑上创建一个新的文件夹,my-first-dapp,然后进入该文件夹。
    • 在终端中运行 truffle init,这将创建一个标准的 Truffle 项目结构,包括:
      • contracts/:存放你的 Solidity 智能合约文件。
      • migrations/:部署脚本文件。
      • test/:测试文件。
      • truffle-config.js:Truffle 的配置文件。
  2. 编写智能合约

    • 打开 contracts/ 文件夹,删除 Migrations.sol(这是 Truffle 自带的,我们暂时用不到),然后创建一个新的 Solidity 文件,SimpleStorage.sol

    • 编写一个简单的智能合约,用于存储和读取一个数字:

      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      contract SimpleStorage {
          uint256 private storedData;
          event DataUpdated(uint256 newValue);
          function set(uint256 x) public {
              storedData = x;
              emit DataUpda
      随机配图
      ted(x); } function get() public view returns (uint256) { return storedData; } }
    • 代码解释

      • SPDX-License-Identifierpragma solidity 是 Solidity 合约的标准开头。
      • contract SimpleStorage { ... } 定义了一个名为 SimpleStorage 的合约。
      • uint256 private storedData; 声明一个私有的无符号256位整型变量 storedData
      • event DataUpdated(uint256 newValue); 定义一个事件,用于在数据更新时通知前端。
      • function set(uint256 x) public:一个公共函数,用于设置 storedData 的值,并触发 DataUpdated 事件。
      • function get() public view returns (uint256):一个公共视图函数,用于读取 storedData 的值,view 表示它不会修改链上状态。
  3. 编译智能合约

    • 确保你的 truffle-config.js 文件已经正确配置(Truffle 初始化后会默认配置好)。
    • 在终端中运行 truffle compile,如果成功,你会在 build/contracts/ 目录下看到编译后的合约 ABI(应用程序二进制接口)和字节码。
  4. 部署智能合约 (测试)

    • 启动 Ganache

      • 如果你安装的是 Ganache CLI,在终端运行 ganache-cli(确保另一个终端窗口在项目根目录)。
      • 如果你使用的是 Ganache GUI,打开它,创建一个新的工作区,选择 "QUICKSTART" 或自定义一个区块链。
      • 记下 Ganache 提供的其中一个测试账户地址和私钥(通常以 0x 开头)。
    • 配置 MetaMask

      • 打开 MetaMask,点击网络选择器,选择 "Custom RPC"。
      • 在 "New RPC URL" 中输入 Ganache 的 RPC URL(通常是 HTTP://127.0.0.1:7545HTTP://localhost:7545,具体看 Ganache 界面显示)。
      • 网络名称可以填写 "Ganache Testnet",链 ID 输入 Ganache 显示的链 ID(通常是 1337 或 5777)。
      • 点击 "保存"。
    • 导入 Ganache 测试账户到 MetaMask

      在 MetaMask 中点击 "导入账户",粘贴 Ganache 提供的测试账户私钥,然后点击 "导入账户",确保该账户有足够的 ETH(Ganache 每个账户默认会分配 100 ETH)。

    • 编写迁移脚本

      • 打开 migrations/ 文件夹,创建一个新的迁移文件,2_deploy_contracts.js(数字表示部署顺序)。

      • const SimpleStorage = artifacts.require("SimpleStorage");
        module.exports = function (deployer) {
          deployer.deploy(SimpleStorage);
        };
    • 执行部署

      • 在终端中运行 truffle migrate --network development(如果你的 truffle-config.js 中默认网络是 development,可以省略 --network development)。
      • 如果部署成功,你会在终端看到合约的地址,并在 Ganache 界面看到新的交易记录。

与智能合约交互 (前端 DApp)

  1. 创建前端项目
    • 在项目根目录下创建一个新的文件夹 frontend,然后进入该文件夹。
    • 运行 npm init -y 初始化一个 Node.js 项目。
    • 安装必要的依赖:
      • web3:用于与以太坊节点交互的 JavaScript 库。
      • reactreact-dom (如果你想用 React):流行的前端框架。
      • 这里我们先用原生 JavaScript 示例,所以先安装 web3npm install web3
    • 创建一个简单的 HTML 文件 index.htmlfrontend 目录下:
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>SimpleStorage DApp</title>
          <style>
              body { font-family: Arial, sans-serif; margin: 20px; }
              input, button { padding: 8px; margin: 5px; }
          </style>
      </head>
      <body>
          <h1>SimpleStorage DApp</h1>
          <div>
              <label for="valueInput">Set Value:</label>
              <input type="number" id="valueInput" placeholder="Enter a number">
              <button onclick="setValue()">Set Value</button>
          </div>
          <div>
              <button onclick="getValue()">Get Value</button>
              <p>Current Value: <span id="currentValue">