脚本宝典收集整理的这篇文章主要介绍了初遇NFT-IPFS,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
本次学习如何使用Hardhat框架制作可预售的NFT并利用IPFS存储元数据。
NFT全称Non-fungible Token(即非同质化通证)。不可分割性(目前有碎片化协议暂且不谈)且独一无二。这有点对应现实资产比如古董、艺术品。即使是同一批厂家或者艺术家创作也难保证一模一样。
1 mkdir nft_1 2 cd nft_1 3 npm init -y 4 npm install --save-dev hardhat
运行hardhat
npx hardhat
我们选择:basic sample project 然后全程默认回车
创建好的项目目录:
文件contracts 是存放我们写的智能合约 node_modules 是安装的一些插件 scripts 是部署合约调用合约 test 是编写测试脚本
安装waffle 、ethers chai web3等插件npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-web3 web3 安装openzeppelin 合约 npm install @openzeppelin/contracts 安装验证etherscan插件 npm install --save-dev @nomiclabs/hardhat-etherscan 为了安全 使用.env npm install dotenv
插件安装完成后我们需要在项目里添加。
require("@nomiclabs/hardhat-waffle"); require("@nomiclabs/hardhat-web3"); require("@nomiclabs/hardhat-ethers"); require("@nomiclabs/hardhat-etherscan"); require('dotenv').config();
结果如图所示
//编译器版本 pragma solidity ^0.8.0; //导入openzeppelin库 //Ownable 是openzeppelin实现管理员 import '@openzeppelin/contracts/access/Ownable.sol'; //ERC721是NFT常用的标准协议 import '@openzeppelin/contracts/token/ERC721/ERC721.sol'; //可以枚举 import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; //我们创建的合约需要继承上面的合约 contract MyNFT is ERC721, ERC721Enumerable, Ownable { //开启售卖nft bool public _isSaleActive = false; // Constants //设置NFT数量 uint256 constant public MAX_SUPPLY = 2048; //售卖NFT的价格 uint256 public mintPrice = 0.01 ether; //账户最多拥有的NFT数量 uint256 public maxBalance = 6; //账户一次性最多铸造的数量 uint256 public maxMint = 3; //基本url string private _baseURIExtended; event TokenMinted(uint256 supply); event SaleStarted(); event SalePaused(); event AuctionStarted(); event AuctionPaused(); constructor() ERC721('MoonStart', 'ms') {} //开始预售 function startSale() public onlyOwner { _isSaleActive = true; emit SaleStarted(); } //暂停预售 function pauseSale() public onlyOwner { _isSaleActive = false; emit SalePaused(); } //设置价格 function setMintPrice(uint256 _mintPrice) public onlyOwner { mintPrice = _mintPrice; } //设置拥有NFT数量 function setMaxBalance(uint256 _maxBalance) public onlyOwner { maxBalance = _maxBalance; } //设置最大mint数量 function setMaxMint(uint256 _maxMint) public onlyOwner { maxMint = _maxMint; } //提取合约中的ETH function withdraw(address to) public onlyOwner { uint256 balance = address(this).balance; payable(to).transfer(balance); } //返回当前总量 function getTotalSupply() public view returns (uint256) { return totalSupply(); } //获取地址拥有的nft function getMoonStarByOwner(address _owner) public view returns (uint256[] memory) { uint256 tokenCount = balanceOf(_owner); uint256[] memory tokenIds = new uint256[](tokenCount); for (uint256 i; i < tokenCount; i++) { tokenIds[i] = tokenOfOwnerByIndex(_owner, i); } return tokenIds; } //mint NFT function mintMoonStar(uint numMoonStars) public payable { require(_isSaleActive, 'Sale must be active to mint MoonStars'); require(totalSupply() + numMoonStars <= MAX_SUPPLY, 'Sale would exceed max supply'); require(balanceOf(msg.sender) + numMoonStars <= maxBalance, 'Sale would exceed max balance'); require(numMoonStars <= maxMint, 'Sale would exceed max mint'); require(numMoonStars * mintPrice <= msg.value, 'Not enough ether sent'); _mintMoonStar(numMoonStars, msg.sender); emit TokenMinted(totalSupply()); } //mint 函数具体实现 function _mintMoonStar(uint256 numMoonStars, address recipient) internal { uint256 supply = totalSupply(); for (uint256 i = 0; i < numMoonStars; i++) { _safeMint(recipient, supply + i); } } //设置基本url 主要后面拼接 function setBaseURI(string memory baseURI_) external onlyOwner { _baseURIExtended = baseURI_; } //获取基本url function _baseURI() internal view virtual override returns (string memory) { return _baseURIExtended; } //得到nft的url function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), 'ERC721Metadata: URI query for nonexistent token'); return string(abi.encodePacked(_baseURI(), tokenId.toString())); } //转移这里使用了hooks function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(from, to, tokenId); } // IERC165 接口的实现 function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } }
const main = async () => { const nftContractFactory = await hre.ethers.getContractFactory('MyNFT'); const nftContract = await nftContractFactory.deploy(); await nftContract.deployed(); console.log("Contract deployed to:", nftContract.address); }; const runMain = async () => { try { await main(); process.exit(0); } catch (error) { console.log(error); process.exit(1); } }; runMain();
由于我喜欢在remix 调试,这里就只用部署合约,没有进行函数调用
npx hardhat run scripts/run.js
无报错,智能合约没问题。
module.exports = { solidity: "0.8.4", };
修改完成的是
module.exports = { solidity: "0.8.4", networks: { rinkeby: { url:process.env.STAGING_ALCHEMY_KEY, accounts:[process.env.PRIVATE_KEY], }, },etherscan: {apiKey:process.env.API_KEY}};
npx hardhat run scripts/run.js --network rinkeby
上面的0xe4 就是合约地址,部署成功,我们现在打开remix https://remix.ethereum.org/
点击左边栏的 Deploy & run transactions 在ENVIRIONMENT 选择Injected Web3 这个可以让remix 链接我们的小狐狸钱包,然后再CONTRACT 找到 MyNFT -contracts/MyNFT.sol接着下面 At Address 粘贴我们上面得到的合约地址,然后点击 At Address。
现在我们来交互我们的智能合约, 点击箭头部分,再找到startsale 必须使用部署这个合约的账号
先开启 售卖
我们再来mint 1个NFT,此时需要我们发送eth。由于在remix 无法直接填写0.01ether,需要单位换成'wei' 这是最小单位10000000000000000 wei==0.01ether 1ether==10^18 wei。我这里演示mint 2个
看链上返回结果,已经成功。
{ "name": "MoonStart", "description": "test NFT", "attributes": [ { "trait_type": "Background", "value": "Galaxy" }, { "trait_type": "color", "value": "blue" } ], "image": "https://ipfs.io/ipfs/xxx/1.png" }
就像这样,我们需要复制CID,待会添加到json里
然后又通过pinata上传
然后复制CID,返回remix中 调用函数 setbaseURI
这里我们填写的是 ipfs://Qmxxxx/
未完待续---------散花
在验证合约这里折腾了很久,但也学习到了很多。对应这种导入了第三方库的合约 解决办法就是通过 flattener。remix-ide本地版本有这个插件 flattener ,或者使用truffle-flattener把这些合约全都压缩在一个文件 并删除多余的spdx。最佳的方式还是使用插件来自动化验证比如 hardhat truffle 的自动验证合约。
新年快乐
以上是脚本宝典为你收集整理的初遇NFT-IPFS全部内容,希望文章能够帮你解决初遇NFT-IPFS所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。