這項工作的靈感來自這個
在本教程中,我們將創建一個不可替代令牌 (NFT) 並部署到公共測試網。
ERC721 是代表不可替代代幣所有權的標準,也就是說,每個代幣都是獨一無二的,例如在房地產或收藏品中。
我們將使用 OpenZeppelin Contracts 中的 Presets 合約來創建 ERC721 並使用 Truffle 進行部署。
設置環境
我們首先創建一個新項目。
$ mkdir mynft && cd mynft
$ npm init -y
然後我們安裝具有 ERC721 實現的 OpenZeppelin Contracts。
$ npm i --save-dev @openzeppelin/contracts
接下來我們安裝一個用於部署的開發工具,在本教程中,我們將使用 Truffle,但我們可以使用任何其他工具,例如 Buidler、Remix 或 OpenZeppelin CLI。
獲取合約工件
我們將使用 truffle init 設置我們的 Solidity 項目,以創建合約目錄和配置以連接到網絡。
$ npx truffle init
Starting init...
================
> Copying project files to
Init successful, sweet!
我們將使用 Preset ERC721PresetMinterPauserAutoId,這是一個預設的 ERC721,因此可以鑄造(使用自動令牌 ID 和元數據 URI)、暫停和銷毀。
Preset 合約已經編譯好了,所以我們只需要將工件複製到 build/contracts 目錄。
$ mkdir -p build/contracts/
$ cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/
使用您最喜歡的編輯器在遷移目錄中創建 2_deploy.js,其中包含以下內容:
// migrations/2_deploy.js
// SPDX-License-Identifier: MIT
const ERC721PresetMinterPauserAutoId = artifacts.require("ERC721PresetMinterPauserAutoId");
module.exports = function(deployer) {
deployer.deploy(ERC721PresetMinterPauserAutoId, "My NFT","NFT", "http://my-json-server.typicode.com/huangsuyu/nft/tokens");
};
將合約部署到本地區塊鏈
我們將使用 truffle develop 來打開一個帶有開發區塊鏈的 Truffle 控制台
前往水龍頭並請求測試PSC
$ npx truffle develop
Truffle Develop started at http://127.0.0.1:9545/
Accounts:
(0) 0xc7e4bbc4269fdc62f879834e363173aee7895f45
Private Keys:
(0) ef424b4dc91a9c9d6c1fc4ae0a50ce80668f3a955a7e982584b45577e2c70e27
Mnemonic: mechanic cannon setup general indicate people notable frown poet friend credit true
⚠️ Important ⚠️ : This mnemonic was created for you by Truffle. It is not secure.
Ensure you do not use it on production blockchains, or else you risk losing funds.
truffle(develop)> migrate
Compiling your contracts...
===========================
> Compiling ./contracts/Migrations.sol
> Artifacts written to /Users/Documents/work/mynft/build/contracts
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
Starting migrations...
======================
> Network name: 'psctest'
> Network id: 666
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0x9a17a50e6efd52ba3e55245c76c52b065d20587add45aee732c233987033e567
> Blocks: 0 Seconds: 0
> contract address: 0x77409B688eA5461078a31450F3138EA8324F72C9
> block number: 1
> block timestamp: 1604387655
> account: 0xc7e4bBc4269fdC62F879834E363173aeE7895F45
> balance: 99.99616114
> gas used: 191943 (0x2edc7)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00383886 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00383886 ETH
2_deploy.js
===========
Deploying 'ERC721PresetMinterPauserAutoId'
------------------------------------------
> transaction hash: 0xc1a3994c2ad2ba706ac49934b4f480c7b3d9b94241f526afa2dfe91545145a4e
> Blocks: 0 Seconds: 0
> contract address: 0xEaB17D581552123695f03F12b09e378EE9463b44
> block number: 3
> block timestamp: 1604387655
> account: 0xc7e4bBc4269fdC62F879834E363173aeE7895F45
> balance: 99.92142266
> gas used: 3694586 (0x385ffa)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.07389172 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.07389172 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.07773058 ETH
truffle(develop)>
我們可以使用 migrate 將新的 NFT 部署到我們的開發區塊鏈中。
truffle(develop)> migrate
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: 'psctest'
> Network id: 666
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Replacing 'Migrations'
----------------------
> transaction hash: 0x5d71b0a45a0fe20e2ca645393bb44b83fbd47351c009c48be0b8b84b610fb3b7
> Blocks: 0 Seconds: 0
> contract address: 0x3797c825cAC4a1FA765F6D8cd7787fB195849555
> block number: 1
> block timestamp: 1590736865
> account: 0x0445c33BdCe670D57189158b88c0034B579f37cE
> balance: 99.99671674
> gas used: 164163 (0x28143)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00328326 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00328326 ETH
2_deploy.js
===========
Replacing 'ERC721PresetMinterPauserAutoId'
------------------------------------------
> transaction hash: 0x166d7b28f4afb949585b5a0e5b4151daa54acbcb70566b202fd62ab380a6650c
> Blocks: 0 Seconds: 0
> contract address: 0xDEE9411430c7Dd9b67fC6DA723DE729AdAB50AD7
> block number: 3
> block timestamp: 1590736866
> account: 0x0445c33BdCe670D57189158b88c0034B579f37cE
> balance: 99.92191642
> gas used: 3697675 (0x386c0b)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0739535 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.0739535 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.07723676 ETH
然後我們可以使用我們部署的合約。
truffle(develop)> nft = await ERC721PresetMinterPauserAutoId.deployed()
undefined
與我們的代幣互動
我們可以使用的帳戶是在我們開始 truffle development 時顯示的
令牌元數據
我們可以調用合約來讀取代幣元數據,例如名稱、符號和baseURI
truffle(develop)> await nft.name()
'My NFT'
truffle(develop)> await nft.symbol()
'NFT'
truffle(develop)> await nft.baseURI()
Mint
我們可以從具有鑄幣者角色的賬戶向給定賬戶發送交易以鑄幣代幣。 在我們的例子中,我們從部署了代幣的賬戶進行鑄幣,該代幣被賦予鑄幣者角色。 我們將鑄造 1 個通證 ID 為 0 的 NFT。
truffle(develop)> await nft.mint("0x0445c33bdce670d57189158b88c0034b579f37ce")
{ tx:
'0xd301a60dbb8ac187687f6639f200d4e6f2cfa065923092b3940330e35a26421d',
receipt:
{ transactionHash:
'0xd301a60dbb8ac187687f6639f200d4e6f2cfa065923092b3940330e35a26421d',
transactionIndex: 0,
blockHash:
'0x3ad3cfcb26da0c969e9d5a5414a5e90a91a3a862c9e9082afc38a0ec0f1a5d00',
blockNumber: 5,
from: '0x0445c33bdce670d57189158b88c0034b579f37ce',
to: '0xdee9411430c7dd9b67fc6da723de729adab50ad7',
gasUsed: 156470,
...
我們可以檢查令牌的所有者和元數據的令牌 URI
truffle(develop)> await nft.ownerOf(1)
'0x0445c33BdCe670D57189158b88c0034B579f37cE'
truffle(develop)> await nft.tokenURI(1)
元數據 EIP-721 2 包括一個可選的元數據擴展,帶有名稱、符號和每個 tokenID 的 tokenURI,它可以指向帶有給定 token ID 的名稱、描述和圖像的 JSON 文件。
如何創建和託管此元數據取決於您。 我建議使用您控制的域來指向您託管數據的位置,以便您可以根據需要移動它。
對於本教程,我們將使用我的 JSON 服務器,我們可以在其中將單個 JSON 文件存儲在 GitHub 存儲庫中,我們可以通過假 JSON 服務器訪問該文件。
部署到公共測試網
接下來我們將部署到PSC鏈測試網。 要進行部署,我們將使用使用 Truffle 連接到公共測試網絡的說明 您將需要以下內容:
Infura 項目 ID(或您選擇的公共節點提供商)
@truffle/hdwallet-provider 已安裝
為 Rinkeby 網絡配置 truffle-config.js
secrets.json 或其他秘密管理解決方案。 確保不要將其提交到 GitHub!
我的 truffle-config.js 具有以下 rinkeby 配置:
testnet: {
provider: () => new HDWalletProvider(mnemonic, `Rpc:http://47.245.15.162:7012/`),
network_id: 666,
confirmations: 10,
timeoutBlocks: 200,
skipDryRun: true
},
psc: {
provider: () => new HDWalletProvider(mnemonic, `Rpc:http://47.245.15.162:7012/`),
network_id: 666,
confirmations: 10,
timeoutBlocks: 200,
skipDryRun: true
},
部署到 PSC 測試網
$ npx truffle migrate --network testnet
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: psctest
> Network id: 666
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0x9a17a50e6efd52ba3e55245c76c52b065d20587add45aee732c233987033e567
> Blocks: 0 Seconds: 0
> contract address: 0x77409B688eA5461078a31450F3138EA8324F72C9
> block number: 1
> block timestamp: 1604387655
> account: 0xc7e4bBc4269fdC62F879834E363173aeE7895F45
> balance: 99.99616114
> gas used: 191943 (0x2edc7)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00383886 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00383886 ETH
2_deploy.js
===========
Deploying 'ERC721PresetMinterPauserAutoId'
------------------------------------------
> transaction hash: 0xc1a3994c2ad2ba706ac49934b4f480c7b3d9b94241f526afa2dfe91545145a4e
> Blocks: 0 Seconds: 0
> contract address: 0xEaB17D581552123695f03F12b09e378EE9463b44
> block number: 3
> block timestamp: 1604387655
> account: 0xc7e4bBc4269fdC62F879834E363173aeE7895F45
> balance: 99.92142266
> gas used: 3694586 (0x385ffa)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.07389172 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.07389172 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.07773058 ETH
Mint
我們可以從具有鑄幣者角色的賬戶向給定賬戶發送交易以鑄幣代幣。
truffle(develop)> nft = await ERC721PresetMinterPauserAutoId.deployed()
undefined
在我們的例子中,我們從部署了代幣的賬戶進行鑄幣,該代幣被賦予鑄幣者角色。
要查看配置的帳戶,請運行命令 accounts。
truffle(rinkeby)> accounts
[ '0x133d144f52705ceb3f5801b63b9ebccf4102f5ed',
我們將鑄造 1 個通證 ID 為 1 的 NFT。指定您想成為通證持有者的地址(0xc7e4bBc4269fdC62F879834E363173aeE7895F45 是我的測試帳戶之一)
truffle(rinkeby)> await nft.mint("0x133d144f52705ceb3f5801b63b9ebccf4102f5ed")
{ tx:
'0x0d90d4a2a4ac3f33d5220deb11e8f65adf14a6669afd18abd4cce8ca7ab58e04',
receipt:
{ blockHash: '0x724ba66bc1d799820c05a93ae67991b21bb769fd1e9dddd5db9f725f5f633331',
blockNumber: 3333746,
contractAddress: null,
cumulativeGasUsed: 164785,
from: '0x77737a65c296012c67f8c7f656d1df81827c9541',
gasUsed: 164785,
...