如何使用Truffle在Polygon上创建和部署Factory ERC-1155合约

  • QuickNode
  • 发布于 2023-10-17 22:18
  • 阅读 50

本指南介绍了如何使用Truffle在Polygon上创建和部署Factory ERC-1155智能合约,并铸造代表太阳系行星的ERC-1155代币集合。文章详细说明了设置QuickNode Polygon节点,Truffle项目,部署智能合约以及在OpenSea上查看铸造的NFT的步骤。

重要提示

本指南包含对不再积极维护的 Truffle 或 Ganache 的引用。我们建议探索 Hardhat 框架作为替代方案,因为 Consensys 在停止 Truffle 和 Ganache 的维护后与 Hardhat 建立了新的合作伙伴关系。 你可以在此处找到我们与 Hardhat 相关的指南。如果你想查看本指南的更新版本, 请告诉我们

概述

随着 NFT 越来越受欢迎,Polygon 这个快速增长的区块链已成为许多用户和开发人员的首选。 与以太坊相比,Polygon 允许用户和开发人员以更实惠的水平与区块链交互。 出于这些原因,本指南将介绍如何使用 Truffle 在 Polygon 上创建和部署 Factory ERC-1155 智能合约。 为了让事情更有趣,我们铸造的 ERC-1155 代币将代表一个 Solar System NFT 系列(包含八个不同的行星)。 为了创建这个系列,我们收集了八张图片(我们的行星)和八个元数据文件(包括名称、描述和链接字段),并将它们上传到 NFT.Storage。 在本指南结束时,我们将能够在 OpenSea 上查看我们铸造的 NFT:

Mercury ERC-1155 NFT on OpenSea

此外,如果你坚持到最后,我们还会在最后添加一些额外的知识点!

我们将做什么

  • 定义 ERC-1155 标准
  • 使用 QuickNode 设置 Polygon 节点(在此处免费注册here
  • 设置 Truffle 项目
  • 部署 ERC-1155 工厂智能合约
  • 从工厂智能合约中铸造 ERC-1155 代币集合

你需要的

  • 智能合约的基础知识
  • 你自己的图像资产和元数据
  • 安装 Node.js
  • 代码编辑器(例如,VSCode)
  • Web3 钱包(例如,MetaMask、Coinbase Wallet)和 Polygon 主网上的 MATIC
  • Polygonscan API 密钥
依赖项 版本
node.js 18.13.0
@openzeppelin/contracts ^5.0.0
@truffle/hdwallet-provider ^2.1.15
truffle-plugin-verify ^0.6.7

我们现在将概述 ERC-1155 标准、工厂模式、Polygon 和 Truffle。 如果你熟悉这些,请随意跳到“设置 QuickNode 节点”部分。

ERC-1155 标准

ERC-1155 标准于 2018 年提出,并继续被许多 NFT 项目使用。 为什么? 它解决了 ERC-721 标准遇到的一些问题。 让我们更深入地了解它可以做什么:

使用案例

  • 表示可替代、不可替代和部分可替代的代币

  • 在单个交易中发送多个代币

  • 允许原子交换(支持跨两个不同链的交换)

什么是工厂模式?

工厂合约是指可以创建、跟踪和修改其创建的合约状态的智能合约。 你可能想要实施工厂合约有几个用例。 例如,如果你的部署管道涉及重新部署相同的合约,你可以利用工厂模式来跟踪这些合约并节省 gas 费用。

我们在本指南中部署的工厂合约允许我们在一个合约中创建和跟踪多个 ERC-1155 代币。 这使我们能够制作不同的 NFT 系列并从一个地方管理它们。

什么是 Polygon?

Polygon 是公共区块链的扩展解决方案。 基于 Plasma 框架(PoS)的自适应实现 - 具有基于帐户的性能,Polygon 支持所有现有的以太坊工具以及更快、更便宜的交易。

为了将它的增长纳入上下文中,Polygon 的总锁定价值 (TVL) 在不到一年的时间内从 1 亿美元增加到超过 30 亿美元(来源)。 我们还可以通过查看 Polygon 上唯一地址的数量来看到增长:

A line chart of Polygon (PoS) daily transactions

什么是 Truffle?

Truffle 是一个开发环境、测试框架和资源管道,适用于使用以太坊虚拟机 (EVM) 的区块链。 这是一个套件产品,将帮助开发人员在 web3 中快速构建和交付更多出色的产品。 查看 Truffle 主页以了解更多信息。

设置 QuickNode Polygon 节点

为了将我们的合约部署到 Polygon 主网,我们需要运行一个 Polygon 节点。 我们可以运行我们自己的 Polygon 节点,但由于这对于仅部署合约来说可能过于复杂,我们将使用 QuickNode 提供的免费节点来简化操作。 要访问 Polygon 节点,请导航到 QuickNode 并在此处设置一个帐户! 创建免费的 Polygon 节点后,复制你的 HTTP Provider 节点:

Screenshot of Quicknode endpoint

设置项目目录

在你的终端中导航到一个你想要设置此项目的目录,然后运行以下命令:

mkdir nft_project && cd nft_project

然后,安装所需的依赖项(即,Truffle & OpenZeppelin,插件)并运行:

npm install -g truffle

要初始化 npm 和 truffle 项目,请运行:

npm init --y && truffle init

安装必要的依赖项:

npm install @openzeppelin/contracts @truffle/hdwallet-provider truffle-plugin-verify

安装后,你还可以运行命令 node --versiontruffle version 来查看已安装的版本。 如果你看到错误,请确保你的 npm 模块已添加到你的路径。

Truffle 样板模板如下:

  • contracts/:Solidity 合约的目录

  • migrations/:可编写脚本的部署文件的目录

  • test/:用于测试你的应用程序和合约的测试文件的目录

  • truffle-config.js:Truffle 配置文件

要仔细检查项目是否已初始化,请在你的终端中运行 ls 命令。 你应该会看到以下文件和文件夹:

displaying directory contents of truffle project

确认已创建后,你就离在 Polygon 上部署和铸造 NFT 更近一步了!

创建核心合约

现在我们已经验证了我们的 truffle 项目已创建,我们可以开始制作部署我们的 NFT 智能合约所需的文件。

contracts 目录中创建一个名为 _ERC1155Token.sol\_ 的文件。

echo > contracts/ERC1155Token.sol

然后在你的文本编辑器中打开该文件并输入以下代码:

// contracts/ERC1155Token.sol

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

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

contract ERC1155Token is ERC1155, Ownable {

    string[] public names; //string array of names
    uint[] public ids; //uint array of ids
    string public baseMetadataURI; //the token metadata URI
    string public name; //the token mame
    uint public mintFee = 0 wei; //mintfee, 0 by default. only used in mint function, not batch.

    mapping(string => uint) public nameToId; //name to id mapping
    mapping(uint => string) public idToName; //id to name mapping

    /*
    constructor is executed when the factory contract calls its own deployERC1155 method. Note the Ownable(msg.sender) setting the deployer of the ERC-1155 as the owner
    */
    constructor(string memory _contractName, string memory _uri, string[] memory _names, uint[] memory _ids) Ownable(msg.sender) ERC1155(_uri) {
        names = _names;
        ids = _ids;
        createMapping();
        setURI(_uri);
        baseMetadataURI = _uri;
        name = _contractName;
    }

    /*
    creates a mapping of strings to ids (i.e ["one","two"], [1,2] - "one" maps to 1, vice versa.)
    */
    function createMapping() private {
        for (uint id = 0; id < ids.length; id++) {
            nameToId[names[id]] = ids[id];
            idToName[ids[id]] = names[id];
        }
    }
    /*
    sets our URI and makes the ERC1155 OpenSea compatible
    */
    function uri(uint256 _tokenid) override public view returns (string memory) {
        return string(
            abi.encodePacked(
                baseMetadataURI,
                Strings.toString(_tokenid),".json"
            )
        );
    }

    function getNames() public view returns(string[] memory) {
        return names;
    }

    /*
    used to change metadata, only owner access
    */
    function setURI(string memory newuri) public onlyOwner {
        _setURI(newuri);
    }

    /*
    set a mint fee. only used for mint, not batch.
    */
    function setFee(uint _fee) public onlyOwner {
        mintFee = _fee;
    }

    /*
    mint(address account, uint _id, uint256 amount)

    account - address to mint the token to
    _id - the ID being minted
    amount - amount of tokens to mint
    */
    function mint(address account, uint _id, uint256 amount)
        public payable returns (uint)
    {
        require(msg.value == mintFee);
        _mint(account, _id, amount, "");
        return _id;
    }

    /*
    mintBatch(address to, uint256[] memory _ids, uint256[] memory amounts, bytes memory data)

    to - address to mint the token to
    _ids - the IDs being minted
    amounts - amount of tokens to mint given ID
    bytes - additional field to pass data to function
    */
    function mintBatch(address to, uint256[] memory _ids, uint256[] memory amounts, bytes memory data)
        public
    {
        _mintBatch(to, _ids, amounts, data);
    }
}

我们还需要创建一个包含工厂代码的文件。 在 contracts 目录中创建一个名为 `FactoryERC1155.sol` 的文件。

echo > contracts/FactoryERC1155.sol

然后打开该文件并输入以下代码:

// contracts/FactoryERC1155.sol

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

import "./ERC1155Token.sol";

contract FactoryERC1155 {

    ERC1155Token[] public tokens; //an array that contains different ERC1155 tokens deployed
    mapping(uint256 => address) public indexToContract; //index to contract address mapping
    mapping(uint256 => address) public indexToOwner; //index to ERC1155 owner address

    event ERC1155Created(address owner, address tokenContract); //emitted when ERC1155 token is deployed
    event ERC1155Minted(address owner, address tokenContract, uint amount); //emmited when ERC1155 token is minted

    /*
    deployERC1155 - deploys a ERC1155 token with given parameters - returns deployed address

    _contractName - name of our ERC1155 token
    _uri - URI resolving to our hosted metadata
    _ids - IDs the ERC1155 token should contain
    _name - Names each ID should map to. Case-sensitive.
    */
    function deployERC1155(string memory _contractName, string memory _uri, uint[] memory _ids, string[] memory _names) public returns (address) {
        ERC1155Token t = new ERC1155Token(_contractName, _uri, _names, _ids);
        tokens.push(t);
        indexToContract[tokens.length - 1] = address(t);
        indexToOwner[tokens.length - 1] = tx.origin;
        emit ERC1155Created(msg.sender,address(t));
        return address(t);
    }

    /*
    mintERC1155 - mints a ERC1155 token with given parameters

    _index - index position in our tokens array - represents which ERC1155 you want to interact with
    _name - Case-sensitive. Name of the token (this maps to the ID you created when deploying the token)
    _amount - amount of tokens you wish to mint
    */
    function mintERC1155(uint _index, string memory _name, uint256 amount) public {

        uint id = getIdByName(_index, _name);
        tokens[_index].mint(indexToOwner[_index], id, amount);
        emit ERC1155Minted(tokens[_index].owner(), address(tokens[_index]), amount);
    }

    /*
    Helper functions below retrieve contract data given an ID or name and index in the tokens array.
    */
    function getCountERC1155byIndex(uint256 _index, uint256 _id) public view returns (uint amount) {
        return tokens[_index].balanceOf(indexToOwner[_index], _id);
    }

    function getCountERC1155byName(uint256 _index, string calldata _name) public view returns (uint amount) {
        uint id = getIdByName(_index, _name);
        return tokens[_index].balanceOf(indexToOwner[_index], id);
    }

    function getIdByName(uint _index, string memory _name) public view returns (uint) {
        return tokens[_index].nameToId(_name);
    }

    function getNameById(uint _index, uint _id) public view returns (string memory) {
        return tokens[_index].idToName(_id);
    }

    function getERC1155byIndexAndId(uint _index, uint _id)
        public
        view
        returns (
            address _contract,
            address _owner,
            string memory _uri,
            uint supply
        )
    {
        ERC1155Token token = tokens[_index];
        return (address(token), token.owner(), token.uri(_id), token.balanceOf(indexToOwner[_index], _id));
    }
}

现在,让我们开始配置智能合约的编译和部署。

配置和编译智能合约

Truffle 要求你有一个迁移合约才能使用其迁移功能。 这个迁移合约 (Migration.sol) 可以在 contracts 文件夹中找到。 我们的 Truffle 项目还包含一个 migrations 文件夹,该文件夹帮助我们将智能合约部署到区块链上。 我们将在 migrations 文件夹中创建一个名为 `2_deploy_migration.js` 的文件。

echo > migrations/2_deploy_migration.js

然后,输入以下代码:

var factoryContract = artifacts.require("FactoryERC1155");

module.exports = function(deployer){
  deployer.deploy(factoryContract);
}

让我们回顾一下代码。

  • 第 1 行:我们通过 artifact.require() 方法告诉 Truffle 我们想要与哪个合约交互
  • 第 3-5 行:我们通过 module exports 导出一个函数,该函数接受一个 deployer 对象作为其第一个参数,并使用该参数调用我们合约上的 deploy 方法。

*现在我们将运行命令 echo > .secret 创建一个 secret 文件,其中将包含我们帐户的私钥。

echo > .secret

创建一个 `.gitignore` 文件,这样你就不会提交你的私钥。

echo '.secret' >> .gitignore

要在 MetaMask 上找到你的私钥,请查看以下文章:如何导出私钥。 检索到你的私钥后,将内容粘贴到 `.secret` 文件中并保存。

现在是时候设置我们的配置文件了。 幸运的是,我们之抢跑的 truffle init 命令为我们提供了一个可以编辑和配置的样板。 将你的 `truffle-config.js` 文件的内容替换为以下代码。 此文件包含创建我们的配置所需的代码。

// truffle-config.js

const HDWalletProvider = require('@truffle/hdwallet-provider');
const fs = require('fs');
const privateKey = fs.readFileSync(".secret").toString().trim();
const QUICKNODE_PROVIDER = "YOUR_POLYGON_HTTP_ENDPOINT"

module.exports = {
  networks: {
    polygon: {
      provider: () => new HDWalletProvider(privateKey, QUICKNODE_PROVIDER),
      network_id: 137, // change if using a different network other than polygon mainnet
      gasPrice: 40000000000,
      confirmations: 2,    // # of confs to wait between deployments. (default: 0)
      timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
      skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    },
  },
  compilers: {             // Configure your compilers
    solc: {
      version: "0.8.20",    // Fetch exact version from solc-bin (default: truffle's version)
      settings: {          // See the solidity docs for advice about optimization and evmVersion
        optimizer: {
          enabled: true,
          runs: 200
        },
      }
    }
  },
  plugins: [\
    'truffle-plugin-verify'\
  ],
  api_keys: {
    polygonscan: 'YOUR_POLYGONSCAN_APY_KEY'
  }
};

在继续下一步之前,请确保填写以下信息:

1. 记得将你在上一步中检索到的 QuickNode HTTP 节点分配给变量 `YOUR_POLYGON_MAINNET_HTTP_ENDPOINT`。

2. 导航到 Polygonscan 的注册页面并创建一个帐户。 登录后,转到 API 密钥,然后单击“添加”以创建 API 密钥。 创建后,将这些密钥分配给 `api_keys` 下的 _truffle.config.js_ 文件中的变量 `YOUR_POLYGONSCAN_API_KEY`。

polygonscan api keys page

在编译之前,确认你的项目目录已正确设置:

screenshot of project directory

保存文件,然后运行以下命令:

truffle compile

除非另有说明,否则此命令将编译自上次编译以来已更改的合约。

Truffle compilation details

部署工厂合约并铸造 NFT

请注意,在我们运行最后一个命令来部署我们的智能合约之前,我们要确保我们将在其中进行部署的钱包中至少有 1 个 MATIC。

现在是将你的 Factory ERC-1155 合约部署到 Polygon 主网的时候了。 运行以下命令进行部署:

truffle migrate --network polygon

如果你想从头开始重置迁移,你可以使用 --reset 标志。

执行命令后,你应该会看到类似于以下输出的内容:

log of migrations deployment

log of migrations deployment

如果你看到类似于上述的输出,恭喜! 你可以从 ERC1155Factory.sol 迁移过程中复制交易哈希,并将其粘贴到 Polygonscan 中以查看创建的合约。

为了通过 Polygonscan 进行调用并允许其他人查看我们的源代码,请在你的终端中运行以下命令。 这个方便的命令将验证你的合约,以便每个人都可以看到源代码,并且可以使用你合约上的调用/写入功能。

truffle run verify FactoryERC1155  --network polygon

log of verification

验证你的合约后,导航到 Polygonscan 上的已部署合约地址,单击合约选项卡上的“写入合约”按钮,然后连接你的钱包。

Contract tab on Polygonscan

连接你的钱包后,导航到 deployERC1155 函数。 此函数接受五个参数:

  • ERC-1155 代币的名称

  • 元数据集合的 URI。

  • 你的 NFT 集合的 ID。

  • 你的 NFT 的名称。

花点时间将你的图像和元数据资源上传到 NFT.Storage。 如果你需要学习如何操作,请查看此 QuickNode 指南中的“创建元数据 URI”部分。 如果你想创建与本指南相同的集合,请使用以下输入:

Interact with the deployERC1155 function on Polygonscan

我们可以查看交易哈希以获取更多详细信息:

image of transaction receipt for function call to deployERC1155

请注意,你可以单击日志选项卡以查看发出的事件。

上面的交易收据显示了我们已部署的 ERC-1155 代币合约,但我们尚未铸造任何 NFT。 要从我们的 Solar System 系列中铸造 NFT,我们需要调用 mintERC1155 函数。 此函数采用三个参数:

  • 你想要交互的 ERC-1155 的索引。
  • 你希望铸造的代币的名称。
  • 你想要铸造的代币数量。

在此示例中,我们将铸造行星 Mercury 的 NFT。 以下是交易调用和收据的外观:

Interact with the mintERC1155 function on Polygonscan

Transaction receipt on Polygonscan for the function call mintERC1155

现在我们已经铸造了一个 ERC-1155 代币,你可以使用函数 getERC1155byIndexAndId 来获取更多信息:

Contract read functions displayed on polygonscan

就这样! 如果你一直跟随我们,你现在应该在你的钱包中拥有你新铸造的 NFT。 以下是我们的外观:

Wallet activity on polygonscan showing ERC-1155 tokens

我们还可以转到我们在 OpenSea 上的个人资料,并在那里查看已铸造的 NFT:

OpenSea page containing minted NFT of Mercury

最后的想法

如果你做到了这一步,恭喜! 我们知道本指南非常广泛,但希望你学到了一些东西! 对我们在本指南中介绍的内容进行简要回顾:

  • 使用 Truffle 在 Polygon 区块链上部署了一个工厂 ERC-1155 智能合约
  • 从我们的工厂合约中铸造了 ERC-1155 代币
  • 验证了我们的合约代码,使其在 Polygonscan 上可见
  • 使我们的 ERC-1155 合约与 OpenSea 兼容

订阅我们的新闻通讯以获取更多关于以太坊的文章和指南。 如果你有任何反馈意见,请随时通过 Twitter 与我们联系。 你可以随时在我们的 Discord 社区服务器上与我们聊天,其中包含一些你将遇到的最酷的开发人员 :)

我们 ❤️ 反馈!

如果你有任何反馈或新主题的请求,请告诉我们。 我们很乐意听取你的意见。

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

0 条评论

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