【Web3 开发系列教程—创建你的第一个智能合约(2)】部署第一个智能合约

如果你是区块链开发的新手并且不知道从哪里开始,或者你只是想了解如何部署智能合约并与之交互,那么本指南适合你。 我们将介绍使用虚拟钱包 (Metamask)、Solidity、Hardhat 和 Alchemy 在 Goerli 测试网络上创建和部署一个简单的智能合约(如果你还不明白其中的任何含义,请不要担心,我们将 解释一下!)。

创建和部署智能合约

第 1 步:连接到以太坊网络

有很多方法可以向以太坊链发出请求。 为简单起见,我们将在 Alchemy 上使用免费帐户(如果你还没有 Alchemy 帐户,请点击在此处免费注册),这是一个区块链开发平台和 API,允许我们与以太坊链进行通信,而无需运行我们自己的节点。 该平台还具有用于监视和分析的开发人员工具,我们将在本教程中利用这些工具来了解我们的智能合约部署中的幕后情况。

第 2 步:创建应用和 API 密钥

创建 Alchemy 帐户后,你可以通过创建应用程序来生成 API 密钥。 这将允许我们向 Goerli 测试网络发出请求。 如果你不熟悉测试网,请查看官方给出的指南

image.png

将鼠标悬停在导航栏中的“应用程序”上并单击“创建应用程序”,导航到 Alchemy 仪表板中的“创建应用程序”页面:

image.png

将你的应用命名为“Hello World”,提供简短描述,为环境选择“Staging”(用于你的应用记账),然后为你的网络选择“Goerli”。
![image.png](https://img-blog.csdnimg.cn/img_convert/ce5e55e160b6a237b17484666bac14f6.png#clientId=u1fbba3d7-5f94-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=234&id=ub2c28140&margin=[object Object]&name=image.png&originHeight=467&originWidth=1005&originalType=binary&ratio=1&rotation=0&showTitle=false&size=116303&status=done&style=none&taskId=ub085db5e-6645-4ba5-a8a5-82fbfabd4b9&title=&width=502.5)
仔细检查你是否选择了 Goerli 测试网!

点击“创建应用程序”,就是这样! 你的应用程序应显示在下表中。

第 3 步:创建以太坊账户(地址)

我们需要一个以太坊账户来发送和接收交易。 在本教程中,我们将使用 Metamask,这是浏览器中的一个虚拟钱包,用于管理你的以太坊账户地址。 如果你想了解更多关于以太坊交易如何运作的信息,请查看以太坊基金会的这个页面。

你可以在此处免费下载和创建 Metamask 帐户。 当你正在创建帐户时,或者如果你已经有帐户,请确保切换到右上角的“Goerli 测试网络”(这样我们就不会处理真钱)。
image.png

第 4 步:从 Faucet 中添加 ether

为了将我们的智能合约部署到测试网络,我们需要一些虚假的 Eth。 要获取 Eth,你可以前往 Goerli 水龙头并输入你的 Goerli 帐户地址,然后单击“Send Me Eth”。 由于网络流量,可能需要一些时间才能收到你的虚假 Eth。 (在撰写本文时,大约需要 30 分钟。)不久之后,你应该会在你的 Metamask 帐户中看到 Eth!

第 5 步:检查余额

为了仔细检查我们的余额,让我们使用 Alchemy 的 composer 工具发出一个 eth_getBalance 请求。 这将返回我们钱包中的 Eth 数量。
image.png
输入你的 Metamask 帐户地址并单击“发送请求”后,应该会看到如下所示的响应:

{"jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000"}

注意:这个结果是 wei 而不是 eth。 魏被用作以太的最小面额。 wei到eth的换算为:1 eth = 10^18 wei。 因此,如果我们将 0x2B5E3AF16B1880000 转换为十进制,我们会得到 5*10^18,它等于 5 eth。 呸! 我们的假钱就在那里🤑。

第 6 步:初始化我们的项目

mkdir hello-world
cd hello-world

首先,我们需要为我们的项目创建一个文件夹。 导航到你的命令行并键入:

现在我们在项目文件夹中,我们将使用 npm init 来初始化项目。 如果你还没有安装 npm,请按照这些说明进行操作(我们还需要 Node.js,所以也下载它!)。

npm init # (or npm init --yes)

你如何回答安装问题并不重要,以下是我们的做法以供参考:

package name: (hello-world)
version: (1.0.0)
description: hello world smart contract
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

About to write to /Users/.../.../.../hello-world/package.json:

{
   "name": "hello-world",
   "version": "1.0.0",
   "description": "hello world smart contract",
   "main": "index.js",
   "scripts": {
      "test": "echo "Error: no test specified" && exit 1"
   },
   "author": "",
   "license": "ISC"
}

第 7 步:下载 Hardhat

Hardhat 是一个用于编译、部署、测试和调试以太坊软件的开发环境。 在部署到实时链之前,它可以帮助开发人员在本地构建智能合约和 dApp。

在我们的 hello-world 项目中运行:

npm install --save-dev hardhat

第 8 步:创建 Hardhat 项目

在我们的 hello-world 项目文件夹中,运行:

npx hardhat

然后,你应该会看到一条欢迎消息和用于选择你想要执行的操作的选项。 选择“创建一个空的 hardhat.config.js”:

888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

👷 Welcome to Hardhat v2.0.11 👷‍

What do you want to do? …
Create a sample project
❯ Create an empty hardhat.config.js
Quit

这将为我们生成一个 hardhat.config.js 文件,我们将在其中为我们的项目指定所有设置(在第 13 步中)。

第 9 步:添加项目文件夹

为了让我们的项目井井有条,我们将创建两个新文件夹。 在命令行中导航到 hello-world 项目的根目录并键入:

mkdir contracts
mkdir scripts
  • contract: 是我们保存 hello world 智能合约代码文件的地方
  • scripts: 是我们保存脚本以部署和与我们的合约交互的地方

第 10 步:编写我们的合约

你可能会问自己,我们到底什么时候要编写代码? 好吧,我们到了,第 10 步😄

在你最喜欢的编辑器中打开 hello-world 项目(我喜欢 VSCode)。 智能合约是用一种称为 Solidity 的语言编写的,我们将使用它来编写我们的 HelloWorld.sol 智能合约。‌

  1. 导航到“contracts”文件夹并创建一个名为 HelloWorld.sol 的新文件
  2. 下面是我们将在本教程中使用的来自以太坊基金会的 Hello World 智能合约示例。 将以下内容复制并粘贴到你的 HelloWorld.sol 文件中,并确保阅读注释以了解此合约的作用:
// 使用语义版本控制指定 Solidity 的版本。
// 了解更多:https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
pragma solidity >=0.7.3;

// 定义一个名为“HelloWorld”的合约。
// 合约是功能和数据(其状态)的集合。 部署后,合约将驻留在以太坊区块链上的特定地址。 了解更多:https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
contract HelloWorld {

   // 调用更新函数时发出
   // 智能合约事件是你的合约将区块链上发生的事情传达给你的应用程序前端的一种方式,它可以“监听”某些事件并在它们发生时采取行动。
   event UpdatedMessages(string oldStr, string newStr);

   // 声明一个`string`类型的状态变量`message`。
   // 状态变量是其值永久存储在合约存储中的变量。 关键字 `public` 使变量可以从合约外部访问,并创建一个函数,其他合约或客户端可以调用该函数来访问该值。
   string public message;

   // 与许多基于类的面向对象语言类似,构造函数是一种特殊函数,仅在合约创建时执行。
   // 构造函数用于初始化合约的数据。 了解更多:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
   constructor(string memory initMessage) {

      // 接受字符串参数 `initMessage` 并将值设置到合约的 `message` 存储变量中)。
      message = initMessage;
   }

   // 一个接受字符串参数并更新“消息”存储变量的公共函数。
   function update(string memory newMessage) public {
      string memory oldMsg = message;
      message = newMessage;
      emit UpdatedMessages(oldMsg, newMessage);
   }
}

这是一个超级简单的智能合约,它在创建时存储一条消息,并且可以通过调用更新函数来更新。

第 11 步:将 Metamask 和 Alchemy 连接到你的项目

我们已经创建了一个 Metamask 钱包、Alchemy 账户,并编写了我们的智能合约,现在是时候连接这三者了。

从你的虚拟钱包发送的每笔交易都需要使用你唯一的私钥进行签名。 为了向我们的程序提供此权限,我们可以将我们的私钥(和 Alchemy API 密钥)安全地存储在环境文件中。

首先,在你的项目目录中安装 dotenv 包:

npm install dotenv --save

这是一个超级简单的智能合约,它在创建时存储一条消息,并且可以通过调用更新函数来更新。

你的环境文件必须命名为 .env,否则将不会被识别为环境文件。请勿将其命名为 process.env 或 .env-custom 或其他任何名称。

你的 .env 应如下所示:

API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"
PRIVATE_KEY = "your-metamask-private-key"

PRIVATE_KEY 私钥的获取方式参考这篇文章

API_URL 的获取方式可以参考下图:

image.png

为了将这些连接到我们的代码,我们将在第 13 步的 hardhat.config.js 文件中引用这些变量。

第 12 步:安装 Ethers.js

Ethers.js 是一个库,它通过使用更友好的方法包装标准** JSON-RPC **方法,使交互和向以太坊发出请求变得更加容易。

Hardhat 使的集成插件变得非常容易,以获得额外的工具和扩展功能。 我们将利用 Ethers 插件进行合约部署(Ethers.js 有一些超级干净的合约部署方法)。
在你的项目目录的命令行中输入如下命令:

npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"

在下一步中,我们还需要在我们的 hardhat.config.js 中使用以太币。

第 13 步:更新 hardhat.config.js

到目前为止,我们已经添加了几个依赖项和插件,现在我们需要更新 hardhat.config.js 以便我们的项目了解所有这些。

将你的 hardhat.config.js 更新为如下所示内容:

/**
* @type import('hardhat/config').HardhatUserConfig
*/

require('dotenv').config();
require("@nomiclabs/hardhat-ethers");

const { API_URL, PRIVATE_KEY } = process.env;

module.exports = {
   solidity: "0.7.3",
   defaultNetwork: "goerli",
   networks: {
      hardhat: {},
      goerli: {
         url: API_URL,
         accounts: [`0x${PRIVATE_KEY}`]
      }
   },
}

第 14 步:编译我们的合约

为了确保到目前为止一切正常,让我们编译我们的合约。 编译任务是内置安 hardhat 的任务之一。

从命令行运行:

npx hardhat compile

你可能会收到有关源文件中未提供 SPDX 许可证标识符的警告,但无需担心!

第 15 步:编写我们的部署脚本

现在我们的合约已经写好并且我们的配置文件已经准备好了,是时候编写我们的合约部署脚本了。

导航到 /scripts 文件夹并创建一个名为 deploy.js 的新文件,向其中添加以下内容:

async function main() {
   const HelloWorld = await ethers.getContractFactory("HelloWorld");

   // 开始部署,返回一个解析为合约对象的 promise
   const hello_world = await HelloWorld.deploy("Hello World!");
   console.log("Contract deployed to address:", hello_world.address);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

其中:

const HelloWorld = await ethers.getContractFactory("HelloWorld");

ethers.js 中的 ContractFactory 是用于部署新智能合约的抽象,因此 HelloWorld 这里是我们的 hello world 合约实例的工厂。 使用 hardhat-ethers 为 ContractFactory 和 Contract 添加插件时,实例默认连接到第一个签名者(所有者)。

const hello_world = await HelloWorld.deploy();

在 ContractFactory 上调用 deploy() 将启动部署,并返回解析为 Contract 对象的 Promise。 这是为我们的每个智能合约功能提供方法的对象。

第 16 步:部署我们的合约

我们终于准备好部署我们的智能合约了! 切换到命令行并运行:

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

然后,你应该会看到如下内容:

Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570

请复制并粘贴此地址以将其保存在某处,因为我们将在以后的教程中使用此地址,因此你不想丢失它。

如果我们去 Goerli etherscan 并搜索我们的合约地址,我们应该能够看到它已经成功部署。 交易将如下所示:
image.png
发件人地址应该与你的 Metamask 帐户地址匹配,收件人地址将显示“Contract Creation”,但如果我们点击交易,我们将在收件人字段中看到我们的合同地址:
image.png

至此,恭喜你! 你已经在以太坊链上部署了一个智能合约🎉

要了解幕后发生的事情,让我们导航到 Alchemy 仪表板中的 Explorer 选项卡。 如果你有多个 Alchemy 应用程序,请确保按应用程序过滤并选择“Hello World”。
image.png
在这里,你将看到当我们调用 deploy() 函数时,Hardhat/Ethers 在后台为我们进行的一些 JSON-RPC 调用。 这里要提到的两个重要的问题是 eth_sendRawTransaction,它是实际将我们的合约写入 Ropsten 链的请求,以及 eth_getTransactionByHash,它是一个请求读取我们的交易信息给定哈希(发送交易时的典型模式)。

要了解有关发送交易的更多信息,你可以从这里查看有关使用 Web3 发送交易的教程。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码

)">
< <上一篇
下一篇>>