这是一个分步介绍教程,将教你如何在以太坊上创建和部署智能合约。
安装
请注意,在编写任何智能合约代码之前,需要进行某些安装。步骤 1-9 将指导你完成这些安装。智能合约代码将随后发布!
本指南适合那些刚入门区块链开发,不知道从哪里开始,也不知道如何部署和与智能合约交互的人。我们将通过使用 MetaMask、Solidity、Hardhat 和 Alchemy 在 Sepolia 测试网络上创建和部署一个简单的智能合约(如果你还不明白这些意味着什么,请不要担心,我们将解释它!)。
部署完成后你可以在右侧边栏中找到第二部分: 与智能合约交互,以及第三部分:向 Etherscan 提交智能合约。
如果在任何时候有问题,请随时在 Alchemy Discord 中联系我们。
Hardhat
本教程重点介绍 Hardhat 的使用。它是一个构建以太坊的开发环境。Hardhat 是这个领域的新成员,更干净 / 更容易使用,他们也有很多插件使其更可定制。
第一部分:使用 Hardhat 创建部署智能合约
步骤 1:连接到以太坊网络
有很多方法可以向以太坊链发送请求。为简单起见,我们将使用 Alchemy 上的免费账户,这是一个允许我们与以太坊链通信的区块链开发者平台和 API,而不需要自己运行节点。Alchemy 还提供用于监视和分析的开发人员工具;在本教程中,我们将利用这些工具了解我们智能合约部署背后的运作原理。如果你还没有一个 Alchemy 帐户,你可以在这里免费注册。
步骤 2:创建你的应用程序(和 API 密钥)
创建 Alchemy 账户后,你可以通过创建应用程序生成 API 密钥。这将允许你在 Sepolia 测试网络上发送请求。如果你不熟悉测试网络,你可以阅读 Alchemy 关于选择网络的指南。
在 Alchemy 仪表板上,在导航栏中找到 Apps 下拉菜单,然后点击 “Create new app”。
将你的应用程序命名为 Hello World,并写一个简短的描述。确保你在以太坊链上,并选择 Sepolia 作为你的测试网络。
仔细检查你选择的是 Sepolia 测试网络
点击 Create app。你的应用程序将显示新页面中。
你的新应用!
步骤 3:创建以太坊账户(地址)
我们需要一个以太坊账户来发送和接收交易。在本教程中,我们将使用 Metamask,这是一个在浏览器中使用的虚拟钱包,用于管理你的以太坊账户地址。如果你想更多地了解以太坊上的交易原理,请查看以太坊基金会的这个页面。
你可以在这里免费下载并创建一个 Metamask 账户。在创建账户时,或者如果你已经有一个账户,切换到右上角的“Sepolia Test Networks”(以便我们不涉及真实货币)。由于 Sepolia 是一个测试网络,如果你没有看到 Sepolia 作为选项,请确保在 Metamask 设置中打开“Show Test Networks”切换按钮。
步骤 4:从水龙头添加以太币
为了将智能合约部署到测试网络,我们需要一些虚拟以太币。你可以访问 Sepolia 水龙头,在你的 Alchemy 账户中输入你的钱包地址,然后点击“Send Me ETH”来获取ETH。由于网络流量的原因,接收到虚拟以太币可能需要一些时间(在撰写本文时,大约需要30分钟)。你应该很快就能在 Metamask 账户中看到 ETH。
步骤 5:检查你的余额
为了确认我们的余额是否到账,让我们使用 Alchemy 创作工具发出一个 eth_getBalance 请求。这将返回我们钱包中的ETH金额。请查看这个视频,了解如何使用创作工具。
在你输入Metamask账户地址并点击“发送请求”后,你应该会看到一个类似于以下内容的响应:
{"jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000"}
注意
这个结果是以太为单位的 wei。Wei 是以太的最小面额。从 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)。
如何回答初始化问题并不重要。以下是我们的选择参考:
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)
即将写入 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"
}
验证 package.json
,准备好了下一步!
步骤 7:下载 Hardhat
Hardhat 是一个用于编译、部署、测试和调试以太坊软件的开发环境。它可以帮助开发人员在将智能合约和 dapp 部署到生产链之前在本地构建它们时进行调试。
在我们的 hello-world
项目内运行:
npm install --save-dev hardhat
了解更多关于安装说明的详细信息。
步骤 8:创建 Hardhat 项目
在我们的 hello-world
项目文件夹内运行:
npx hardhat
然后你将看到一个欢迎消息和选择你想要执行的操作的选项。选择“create an empty 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.12.2 👷
? What do you want to do? …
Create a JavaScript project
Create a TypeScript project
❯ Create an empty hardhat.config.js
Quit
这将在项目中生成一个 hardhat.config.js
文件。我们稍后将在本教程中使用它来指定我们项目的设置(步骤 13)。
步骤 9:添加项目文件夹
为了保持项目的组织,让我们创建两个新文件夹。在命令行中,导航到 hello-world
项目的根目录,并键入以下命令:
mkdir contracts
mkdir scripts
contracts/
是我们将保留我们的 hello world 智能合约代码文件的地方scripts/
是我们将保留用于部署和与我们的合约交互的脚本的地方
步骤 10:编写我们的合约
你可能会问,我们什么时候才能写代码呢?现在是时候了!
在你喜欢的编辑器中(推荐 VSCode)打开 hello-world 项目。智能合约通常是用 Solidity 编写的,我们将使用它来编写我们的智能合约。
- 导航到
contracts
文件夹,并创建一个名为HelloWorld.sol
的新文件。 - 下面是来自以太坊基金会的 Hello World 智能合约示例,我们将在本教程中使用它。将下面的内容复制到
HelloWorld.sol
文件中,并确保阅读注释以理解此合约的功能:
// SPDX-License-Identifier: UNLICENSED
// Specifies the version of Solidity, using semantic versioning.
// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
pragma solidity >=0.7.3;
// Defines a contract named `HelloWorld`.
// A contract is a collection of functions and data (its state). Once deployed, a contract resides at a specific address on the Ethereum blockchain. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
contract HelloWorld {
//Emitted when update function is called
//Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen.
event UpdatedMessages(string oldStr, string newStr);
// Declares a state variable `message` of type `string`.
// State variables are variables whose values are permanently stored in contract storage. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value.
string public message;
// Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation.
// Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
constructor(string memory initMessage) {
// Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).
message = initMessage;
}
// A public function that accepts a string argument and updates the `message` storage variable.
function update(string memory newMessage) public {
string memory oldMsg = message;
message = newMessage;
emit UpdatedMessages(oldMsg, newMessage);
}
}
这是一个超级简单的智能合约,它在创建时存储一条消息。可以通过调用 update
函数来更新它。
步骤 11:将 MetaMask 和 Alchemy 连接到项目
我们创建了 MetaMask 钱包、Alchemy 账户,并编写了我们的智能合约,现在是时候将这三者连接起来了。
从你的钱包发送的每笔交易都需要使用你独特的私钥进行签名。为了为我们的程序提供这个权限,我们可以将我们的私钥安全地存储在一个环境文件中。我们还将在这里存储 Alchemy 的 API 密钥。
要了解更多关于发送交易的内容,请查看使用 web3 发送交易的教程。
首先,在你的项目目录中安装 dotenv 包:
npm install dotenv --save
然后,在项目的根目录中创建一个 .env
文件。将你的 MetaMask 私钥和 HTTP Alchemy API 地址添加到其中。
你的环境文件必须命名为.env
,否则它将无法被识别为环境文件。不要将其命名为process.env
或.env-custom
或其他任何名称。
- 按照这些说明导出你的私钥
- 点击 View Key 按钮查看下 HTTP Alchemy API 地址
你的 API KEY and HTTP API 地址
你的 .env
文件应该像这样:
API_URL = "https://eth-ropsten.alchemyapi.io/v2/your-api-key"
PRIVATE_KEY = "your-metamask-private-key"
要实际将它们连接到我们的代码中,我们将在步骤 13 的 hardhat.config.js
文件中引用这些变量。
步骤 12:安装 Ethers.js
Ethers.js 是一个库,它通过更友好的方法封装了标准 JSON-RPC 方法 ,使得与以太坊进行交互和发送请求更加容易。
Hardhat 允许我们集成插件以获得额外的工具和扩展功能。我们将利用 Ethers 插件进行合约部署。
在你的项目目录中输入:
npm install ethers@5.7.2
在下一步的 hardhat.config.js
中我们也需要 ethers。
npm install --save-dev @nomiclabs/hardhat-ethers
注意:如果你安装了 ether 的较早版本,即ether ^6.0.0+,则可能会在安装 hardhart-ether 时遇到问题,因为 hardhat具有对等依赖关系。你可以使用--force
或--legacy-peer-deps
标志来忽略这些警告并安装 hardhat-etherscan,即npm install--save-dev @nomiclabs/hardhat-ether--legacy-peer-deps
步骤 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: "sepolia",
networks: {
hardhat: {},
sepolia: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
}
}
}
第 14 步:编译我们的合约
为了确保到目前为止一切正常,让我们编译我们的合约。compile
任务是 Hardhat 内置的任务之一。
在命令行中运行:
npx hardhat compile
你可能会收到有关“在源文件中未提供 SPDX 许可证标识符”的警告,但不用担心——希望一切都看起来不错!如果有问题,你可以随时在Alchemy Discord中留言。
第 15 步:编写我们的部署脚本
既然我们的合约已经编写好,配置文件也准备就绪,现在是时候编写我们的合约部署脚本了。
导航到 scripts/
文件夹,创建一个名为 deploy.js
的新文件,并将以下内容添加到其中:
async function main() {
const HelloWorld = await ethers.getContractFactory("HelloWorld");
// Start deployment, returning a promise that resolves to a contract object
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);
});
Hardhat 非常出色地在合约教程中解释了代码中每一行的作用,我们在这里采用了他们的解释。
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 sepolia
然后,你应该会看到类似以下的输出:
Contract deployed to address: 0xDe511981CC4C5946824867E0f479aC133F84E029
请保存这个地址。我们将在本教程的后面部分中使用它。
如果我们转到 https://sepolia.etherscan.io 并搜索我们的合约地址,我们应该能够看到它已经成功部署。交易将会看起来像这样:
From
地址应该与你的 MetaMask 账户地址匹配,To
地址将会显示 “Contract Creation”。如果我们点击交易,我们将在 To
字段中看到我们的合约地址。
恭喜!你刚刚在以太坊测试网络上部署了一个智能合约。
为了深入了解底层发生了什么,让我们转到 Alchemy 仪表板的资源管理器标签页。如果你有多个 Alchemy 应用程序,请确保按应用程序筛选并选择 “Hello World”。
在这里,你将看到 Hardhat/Ethers 在我们调用 .deploy()
函数时为我们在底层创建的一些 JSON-RPC 方法。这些方法中的两个重要方法是eth_sendRawTransaction
,它实际上是将我们的合约写入 Sepolia 链的请求,以及eth_getTransactionByHash
,它是一个根据哈希值读取我们的交易信息的请求(发送交易时的典型模式)。要了解更多关于发送交易的内容,请查看我们的如何在以太坊上发送交易的教程。
第二部分:与智能合约交互
既然我们已经成功地在 Sepolia 网络上部署了一个智能合约,让我们学习如何与它交互。
第 1 步:创建一个 interact.js 文件
这是我们将编写交互脚本的文件。我们将使用你在第一部分中安装的 Ethers.js 库。
在 scripts/
文件夹内,创建一个名为 interact.js
的新文件,并添加以下代码:
// interact.js
const API_KEY = process.env.API_KEY
const PRIVATE_KEY = process.env.PRIVATE_KEY
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS
第 2 步:更新你的 .env 文件
我们将使用新的环境变量,因此需要在之前创建的 .env 文件中定义它们。
我们需要为 Alchemy API_KEY
和 CONTRACT_ADDRESS
添加定义。
你的 .env
文件应该如下所示:
# .env
API_URL = "https://eth-ropsten.alchemyapi.io/v2/<your-api-key>"
API_KEY = "<your-api-key>"
PRIVATE_KEY = "<your-metamask-private-key>"
CONTRACT_ADDRESS = "0x<your contract address>"
第 3 步:获取你的合约 ABI
我们的合约 ABI(应用程序二进制接口)是与我们的智能合约交互的接口。你可以在这里了解更多关于 合约 ABI 的信息。Hardhat 会自动生成一个 ABI 并将其保存在 HelloWorld.json
中。为了使用 ABI,我们需要解析出其中的内容,并将以下代码添加到我们的 interact.js
文件中:
// interact.js
const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")
如果你想看到 ABI,可以将其打印到控制台上:
console.log(JSON.stringify(contract.abi))
要将 ABI 打印到控制台上,请导航到终端并运行Hardat:
npx hardhat run scripts/interact.js
第 4 步:创建你的合约实例
要与我们的合约交互,我们需要在代码中创建一个合约实例。为此,我们将使用 Ethers.js 的三个概念:
- Provider:一个节点提供程序,为你提供对区块链的读写访问权限
- Signer: 表示可以签署交易的以太坊账户
- Contract:一个在链上部署的特定合约的 Ethers.js 对象
我们将使用上一步中的合约 ABI 来创建我们的合约实例:
// interact.js
const ethers = require('ethers');
// Provider
const alchemyProvider = new ethers.providers.JsonRpcProvider(API_URL);
// Signer
const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider);
// Contract
const helloWorldContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);
要详细了解提供程序、签名者和合约,请参阅ethers.js 文档。
第 5 步:读取初始消息
还记得我们在部署合约时使用的 initMessage = "Hello world!"
吗?现在我们将读取存储在我们智能合约中的初始消息,并将其打印到控制台上。
在 JavaScript 中,与网络交互时通常使用异步函数。要了解更多关于异步函数的信息,阅读这篇异步函数文章。
使用以下代码调用我们智能合约中的 message
函数并读取初始消息:
// interact.js
// ...
async function main() {
const message = await helloWorldContract.message();
console.log("The message is: " + message);
}
main();
在终端中运行 npx hardhat run scripts/interact.js
,你应该会看到如下响应:
The message is: Hello world!
恭喜!你刚刚成功地从以太坊区块链中读取了智能合约数据,太棒了!
第 6 步:更新消息
与其仅仅读取消息,我们也可以使用 update
函数更新我们智能合约中保存的消息!相当酷,对吧?
为此,我们可以直接在实例化的Contract 对象上调用 update
函数,如下所示:
// interact.js
// ...
async function main() {
const message = await helloWorldContract.message();
console.log("The message is: " + message);
console.log("Updating the message...");
const tx = await helloWorldContract.update("This is the new message.");
await tx.wait();
}
main();
请注意,我们在返回的交易对象上调用 .wait()
。这确保我们的脚本在退出函数之前等待交易在区块链上被挖掘。如果不包含 .wait()
调用,脚本可能无法看到合约中的更新的 message
值。
第 7 步:读取新消息
你应该能够重复第 5 步来读取更新后的 message
值。请花些时间看看是否可以进行必要的更改以在终端上打印出新值!
如果你需要提示,以下是此时你的 interact.js
文件应该是什么样子:
// interact.js
const API_URL = process.env.API_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;
const ethers = require('ethers');
const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json");
// provider - Alchemy
const alchemyProvider = new ethers.providers.JsonRpcProvider(API_URL);
// signer - you
const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider);
// contract instance
const helloWorldContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);
async function main() {
const message = await helloWorldContract.message();
console.log("The message is: " + message);
console.log("Updating the message...");
const tx = await helloWorldContract.update("this is the new message");
await tx.wait();
const newMessage = await helloWorldContract.message();
console.log("The new message is: " + newMessage);
}
main();
现在只需运行脚本,你应该能够在终端上看到旧消息、更新状态和新消息的打印输出!
npx hardhat run scripts/interact.js --network sepolia`
The message is: Hello World!
Updating the message...
The new message is: This is the new message.
在运行该脚本时,你可能会注意到 Updating the message... 步骤在新消息加载之前需要等待一段时间。这是由于挖掘过程造成的;如果你对在挖掘时跟踪交易的情况感兴趣,请访问Alchemy 内存池查看交易的状态。如果交易被丢弃,检查 Sepolia Etherscan 并搜索你的交易哈希也是很有帮助的。
就是这样!你现在已经部署并与以太坊智能合约进行交互。如果你想将你的合约发布到 Etherscan,以便任何人都将知道如何与之交互,请查看第 3 部分:向 Etherscan 提交智能合约!
第三部分:向 Etherscan 提交智能合约
你已经完成了将你的智能合约带到生活中的所有艰辛工作,现在是与世界分享的时候了!通过在 Etherscan 上验证你的智能合约,任何人都可以查看你的源代码并与你的智能合约进行交互。让我们开始吧!
步骤 1:在 Etherscan 账户上生成 API 密钥
要验证你拥有要发布的智能合约,你需要一个 Etherscan API 密钥。
注册 Etherscan
如果你还没有 Etherscan 账户,使用这个链接注册一个账户。
一旦登录,找到导航栏中的用户名,将鼠标悬停在上面,然后选择 My profile 按钮。
Etherscan 个人资料
接下来,导航到左侧标签栏的 “API-KEYs” 按钮。点击 “Add” 按钮创建一个新的 API 密钥,将你的应用命名为你想要的任何名字(我们选择了hello-world),然后选择 continue。
创建新的 API 密钥令牌
一旦你遵循了上面的步骤,你应该能够查看你的新 API 密钥,我们在下面用红色突出显示。将此 API 密钥复制到剪贴板。
生成 API 密匙
让我们更新你的 .env
文件,以包含你的 Etherscan API 密钥。如果你正在遵循 Hardhat 教程,你的 .env
文件应该如下所示:
API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key"
API_KEY = "your-api-key"
PRIVATE_KEY = "your-private-account-address"
ETHERSCAN_API_KEY = "your-etherscan-key"
步骤 2:使用 Hardhat 部署智能合约
安装 hardhat-etherscan 插件
使用 Hardhat 将合约发布到 Etherscan 非常简单。首先,你需要安装 hardhat-etherscan
插件才能开始。hardhat-etherscan
将自动验证 Etherscan 上智能合约的源代码和 ABI。进入 hello-world
目录并运行:
npm install --save-dev @nomiclabs/hardhat-etherscan
注意:如果使用 ether 的早期版本,即ether ^6.0.0+,则可能在安装 hardhart-etherscan 时遇到问题,因为 hardhat 的对等依赖关系。你可以使用--force
或--legacy-peer-deps
标志忽略这些警告并安装 hardhat-etherscan,即npm install--save-dev @nomiclabs/hardhat-etherscan--legacy-peer-deps
。
安装完成后,在你的 hardhat.config.js
文件的顶部包括以下语句并添加Etherscan配置选项:
/**
* @type import('hardhat/config').HardhatUserConfig
*/
require('dotenv').config();
require("@nomiclabs/hardhat-ethers");
require("@nomiclabs/hardhat-etherscan");
const { API_URL, PRIVATE_KEY } = process.env;
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;
module.exports = {
solidity: "0.7.3",
defaultNetwork: "sepolia",
networks: {
hardhat: {},
sepolia: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
}
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: ETHERSCAN_API_KEY
}
};
步骤 2:在 Etherscan 上验证你的智能合约
确保你的文件已经正确保存(尤其是你在使用 VSCode),并且你的 .env
变量已经正确配置。
最后,运行验证任务,传递部署的智能合约地址和我们在部署步骤中使用的第一个消息参数字符串:
npx hardhat verify --network sepolia DEPLOYED_CONTRACT_ADDRESS 'Hello World!'
地址验证
确保DEPLOYED_CONTRACT_ADDRESS
是你在 Sepolia 测试网络上部署的智能合约地址。同时,最后一个参数'Hello World!'
必须与你在第一部分的部署步骤中使用的字符串数值相同。
如果一切顺利,你应该在终端中看到以下消息:
Successfully submitted source code for contract
contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address
for verification on Etherscan. Waiting for verification result...
Successfully verified contract HelloWorld on Etherscan.
https://sepolia.etherscan.io/address/<contract-address>#contracts
恭喜!你的智能合约代码现在应该在 Etherscan 上了!继续查看步骤 3 以了解如何查看你的智能合约代码!
步骤 3:在 Etherscan 上查看你的智能合约
当你导航到终端中提供的链接时,你应该能够看到你发布在Etherscan上的智能合约代码和 ABI!
哇哦,你做到了,冠军!现在,任何人都可以调用你的智能合约!我们迫不及待地想看到你接下来构建的东西!
评论 (0)