如何创建一个绑定灵魂的代币

  • QuickNode
  • 发布于 2024-10-06 22:21
  • 阅读 19

本文介绍了Soulbound代币的概念及其安全性,提供了在Sepolia测试网使用Hardhat创建和部署Soulbound代币的详细指南。文中包括所需的配置、合约代码、测试案例以及部署步骤,是一篇结构清晰且内容丰富的技术文章。

概述

Soulbound 代币是一种新的数字资产类型,提供了对你的数字资产更强的安全性和控制力。在本指南中,我们将探讨 Soulbound 代币是什么以及它们是如何工作的。之后,你将学习如何使用 Hardhat 在 Sepolia 测试网络上创建和部署 Soulbound 代币。

你将需要的东西

依赖 版本
node v18.13.0
@openzeppelin/contracts ^4.0.0
@nomicfoundation/hardhat-toolbox ^3.0.0
dotenv ^16.3.1
devDependencies: hardhat ^2.18.1

你将做的事情

  • 了解 Soulbound 代币
  • 用 Solidity 和 Hardhat 创建一个 Soulbound 代币
  • 在 Sepolia 测试网络上测试和部署一个 Soulbound 代币

什么是 Soulbound 代币?

Soulbound 代币是一种只能由特定地址拥有和转移的代币。这意味着一旦创建并分配给某个地址,Soulbound 代币就不能转让或被任何其他地址拥有。这为代币所有者以及可能持有代币的任何人提供了较高的安全性和控制力。

那么,你为什么想使用 Soulbound 代币呢?有几个原因:

  • 安全性: Soulbound 代币为你的数字资产提供更高的安全性,因为它们只能由特定地址拥有和转移。这使得未经授权的个人更难访问或转移你的资产。

  • 控制: 拥有 Soulbound 代币使你对资产拥有完全的控制权,并可以确保它们仅由代币中指定的地址转移或拥有。

  • 自定义: Soulbound 代币可以根据你的特定需求进行自定义,使你能够创建一种独特的数字资产,体现你的价值观和兴趣。

要了解更多关于 Soulbound 代币及其工作原理的信息,我们建议阅读引用文章 https://vitalik.ca/General/2022/01/26/soulbound.html。在这篇文章中,你将找到关于 Soulbound 代币背后概念的详细解释以及它们在以太坊生态系统中的实施方式。

在下一节中,你将学习如何使用 Hardhat 在 Sepolia 测试网络上部署 Soulbound 代币。

开发者设置

通过 QuickNode 访问以太坊 Sepolia

你需要一个 API 端点与 Sepolia 测试网络进行通信。你可以使用公共节点或部署和管理自己的基础设施;然而,如果你希望获得 8 倍更快的响应时间,你可以将重担交给我们。可以在 这里 注册一个免费账户。

登录后,点击“创建端点”,选择以太坊链和 Sepolia 测试网络。

创建端点后,请保留 HTTP Provider URL,因为在设置 hardhat.config.js 文件时你将需要它。

QuickNode 端点

非托管 Web3 钱包设置

你需要访问私钥以便部署本指南中实现的 Soulbound 代币。你可以使用多种选项,例如 MetaMaskCoinbase WalletTorus。请注意,这不是完整列表,还有许多其他优秀的非托管 Web3 钱包可用。

为了快速开始开发,我们将使用支持多条链和网络(包括 Sepolia!)的 Torus 生成一个以太坊账户。

要开始,请访问 Torus 并按照说明生成私钥。

Torus 钱包生成

在进入下一节之前,请确保你在 Sepolia 测试网络地址上有足够的资金以支付合约部署费用。你可以在 Multi-Chain QuickNode Faucet 上接收测试 ETH。请注意,水龙头请求资金需要主网有 0.001 ETH。

项目设置

首先,请确保你的机器上安装了 Node.js 版本 18 或更高。你可以使用以下命令检查 Node.js 的版本

mkdir soulbound-tokens && cd soulbound-tokens

然后,初始化一个默认的 npm 项目:

npm init -y

接下来,我们将根据建议通过开发依赖项安装 Hardhat:

npm install --save-dev hardhat

安装其他依赖项:

npm install dotenv @nomicfoundation/hardhat-toolbox @openzeppelin/contracts@4.0.0

最后,我们通过运行以下终端命令创建一个 Hardhat 项目:

npx hardhat init

当被询问选择哪个项目模板时,选择最后一个选项:创建一个空的 hardhat.config.js

可选步骤

你还可以创建一个 .env 文件来存储你的凭据。如果你决定不创建这个文件,你的私钥和 RPC URL 将硬编码在 hardhat.config.js 文件中。

在你的项目根目录中创建的 .env 文件中,使用以下环境变量:

RPC_URL=<FILLME>
PRIVATE_KEY=<FILLME>

记得保存文件!


现在,打开你选择的代码编辑器(我喜欢使用 VSCode),打开 hardhat.config.js 文件并包含以下代码:

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.4",
  networks: {
    sepolia: {
      url: process.env.RPC_URL,
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};

此文件包含运行 Hardhat 任务和脚本的各种选项和参数。它还包括我们从 .env 文件中导入的环境变量。

创建 Soulbound 代币

接下来,我们将创建 Soulbound 代币智能合约。创建一个名为 contracts 的文件夹作为你的智能合约目录,并包含一个名为 soulbound.sol 的 Solidity 文件:

mkdir contracts && echo > contracts/soulbound.sol

然后打开 soulbound.sol 文件并粘贴以下代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Soulbound is ERC721, ERC721URIStorage, Ownable {

    uint256 private _tokenIdCounter;

    constructor() ERC721("SoulBound", "SBT") {}

    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        internal
        override
    {
        require(from == address(0), "Token not transferable");
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function safeMint(address to) public onlyOwner {
        _tokenIdCounter += 1;
        _safeMint(to, _tokenIdCounter);
    }

    // 以下函数是 Solidity 需要的覆盖。

    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }
}

请注意,Soulbound 代币不可转让的核心部分来自上面的 _beforeTokenTransfer 函数。它是一个内部函数,重写了基类合约中同名的函数。该函数确保代币只能被创建(铸造),而不能转移到其他地址。

现在,我们需要编译合约。编译智能合约涉及将合约的高级语言代码(如 Solidity)转换为可以在以太坊虚拟机(EVM)上执行的机器可读字节码。

要编译合约,运行:

npx hardhat compile

你应该会看到类似于以下内容的输出:

Compiled 13 Solidity files successfully

测试 Soulbound 代币

智能合约测试是区块链开发中的一个重要方面,因为它确保在区块链网络上部署的智能合约的可靠性和安全性。通过彻底测试智能合约,开发人员可以发现并修复可能在实时部署之前导致问题的错误、安全漏洞和其他问题。这有助于防止潜在的财务损失和其他负面后果。

我们测试的主要目标将是确保我们铸造到特定钱包的 Soulbound 代币是不可转让的。话虽如此,让我们编写一些测试!

在你的 soulbound-token 目录中,创建一个名为 test 的文件夹,并创建一个名为 soulbound-test.js 的文件:

mkdir test && echo > test/soulbound-test.js

打开 soulbound-test.js 文件并输入以下 JavaScript 代码:

const { expect } = require("chai");

describe("Soulbound Token Test", function () {
    let owner;

    beforeEach(async function () {
        // 从 ethers 中获取默认账户
        [owner] = await ethers.getSigners();

        // 一个帮助程序来获取合约实例并在本地部署它
        const Soulbound = await ethers.getContractFactory("Soulbound");
        soulbound = await Soulbound.deploy();

        // 向所有者地址铸造代币 ID 1
        await soulbound.safeMint(owner.address);

    });

    it("check the owner is correct", async () => {
        // 检查所有者地址是否拥有代币 ID 0
        const value = await soulbound.ownerOf(1);
        expect(value).to.equal(owner.address);
    });

    it("should revert when trying to transfer via safeTransferFrom", async () => {

        // 请注意,批准函数调用无论如何都会失败
        const approve = await soulbound.approve("0x000000000000000000000000000000000000dEaD", 1)

        await expect(soulbound['safeTransferFrom(address,address,uint256)'](
            owner.address,
            "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5",
            1 // 代币 ID
        )).to.be.reverted;

    });

    it("should revert when trying to transfer via transferFrom", async () => {

        // 请注意,批准函数调用无论如何都会失败
        const approve = await soulbound.approve("0x000000000000000000000000000000000000dEaD", 1)

        await expect(soulbound['transferFrom(address,address,uint256)'](
            owner.address,
            "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5",
            1 // 代币 ID
        )).to.be.reverted;

    });
});

花几分钟时间查看测试代码。

一旦你准备好运行测试文件,在项目根目录中运行以下终端命令:

npx hardhat test

如果你有多个测试文件,可以使用文件的位置指定测试:npx hardhat test test/soulbound-test.js

测试运行后,你应该会看到以下输出:

  Soulbound Token Test
    ✔ check the owner is correct
    ✔ should revert when trying to transfer via safeTransferFrom
    ✔ should revert when trying to transfer via transferFrom

  3 passing (1s)

如果你得到了所有的勾选标记,恭喜你!你已准备好部署到 Sepolia 测试网络。

部署 Soulbound 代币

经过编译和测试,我们可以将 Soulbound 代币部署到远程测试网络。

首先,在你的 soulbound-token 目录中,创建一个名为 scripts 的文件夹,并创建一个名为 deploy.js 的文件:

mkdir scripts && echo > scripts/deploy.js

打开文件并包含以下部署代码:

// 导入 Hardhat 库
const hre = require("hardhat");

// 定义一个 async 函数来处理部署
async function deploy() {
    // 获取 Soulbound 合约
    const Soulbound = await hre.ethers.getContractFactory("Soulbound");
    // 部署 Soulbound 合约
    const soulbound = await Soulbound.deploy();

    // 等待交易被挖掘
    await soulbound.waitForDeployment()

    // 输出部署合约的地址
    console.log("Soulbound token deployed at:", soulbound.target);
}

deploy()
    .then(() => console.log("Deployment complete"))
    .catch((error) => console.error("Error deploying contract:", error));

上述脚本将部署 Soulbound 代币,并记录合约地址或在部署过程中出现的任何错误。花一点时间阅读代码注释,以查看逻辑包含的内容。

一旦你在钱包中有足够的测试 ETH 来部署合约,运行以下命令:

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

你将看到带有 Soulbound 代币合约地址和消息“部署完成”的输出:

终端中的部署

现在,访问 Etherscan for Sepolia 并确认你的 Soulbound 代币已部署。

在我们结束本指南之前,你可以基于此指南学习到的一些想法是:

  • 每当 ERC-721 被销毁时铸造一个 Soulbound 代币
  • 创建一个前端,白名单 Soulbound 代币持有者访问仅限会员的内容

最终想法

就是这样!现在你知道 Soulbound 代币是什么以及如何使用 Hardhat 创建和部署它们。

你在以太坊上构建了什么?在 DiscordTwitter 与我们分享你的想法。如果你对本指南有任何反馈或问题,我们非常乐意听取你的意见!

我们 ❤️ 反馈!

告诉我们 如果你有任何反馈或对新主题的请求。我们很想听到你的声音。

  • 原文链接: quicknode.com/guides/eth...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。