2021年NFT火的一塌糊涂,称之为NFT元年也不为过。
而盲盒玩法又为其增加了可玩性和吸引力。
今年2月份,阿狸 ALI&HIS FRENS NFT元数据泄漏导致盲盒变明盒。
今天就来分享下NFT盲盒的玩法。
编写智能合约
// 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/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
/// @custom:security-contact bluequin@163.com
contract FdfNFT is ERC721, ERC721URIStorage, ERC721Burnable, AccessControl {
using Counters for Counters.Counter;
//是否开启盲盒
bool private _blindBoxOpened = false;
//设置盲盒uri
string baseUri;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
Counters.Counter private _tokenIdCounter;
constructor() ERC721("FDF20220325FNFT", "FDF20220325FNFT") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
}
function setBaseUri(string memory _baseUri) public {
require(
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),
"BaseERC721Uri: only admin can do this action"
);
baseUri = _baseUri;
}
function setBlindBoxOpened(bool _status) public {
require(
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),
"BaseERC721BlindBox: only admin can do this action"
);
_blindBoxOpened = _status;
}
function safeMint(address to, string memory uri) public onlyRole(MINTER_ROLE) {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// The following functions are overrides required by Solidity.
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
virtual
override(ERC721, ERC721URIStorage)
returns (string memory)
{
if(_blindBoxOpened){
return super.tokenURI(tokenId);
}else {
return baseUri;
}
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
发布合约到rinkeby测试环境
这里直接用remix发布就行
在浏览器中查看合约部署情况。 这里看到合约已经创建成功,合约地址 0x5a501c079DB0BeB9A50aCA810be9d7277080E1B4
编写图片服务器接口
图片可以上传到ipfs,但考虑到需要收额外的手续费,以及更加灵活的和前端调用,所以这里采用自己编写服务器接口
接口代码,笔者这里使用java编写
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (1, '开启盲盒,单车变摩托', '开启盲盒,单车变摩托', 'https://lh3.googleusercontent.com/Op-cRm7h8p34PvxvzZbHh5nAmkS2rVZYil1lUYfyKrI4WuEOTG9X3_C1KvtlXGdyfwG_5wyfyOBwIytw9JZVcAkPtXq4PAdLOsmS=w340');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (2, '111', '朋克汽车', 'https://img01.jituwang.com/190326/256609-1Z326042P376.jpg');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (3, '222', '朋克', 'https://img01.jituwang.com/190330/256613-1Z33016444621.jpg');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (4, '333', '朋克', 'https://pic.ntimg.cn/file/20220107/32652940_141026506103_2.jpg');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (5, '444', '金克斯', 'https://pic.ntimg.cn/file/20220218/33805678_164928525106_2.jpg');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (6, '555', '源计划', 'https://img0.baidu.com/it/u=2501200624,302351145&fm=253&fmt=auto&app=138&f=PNG');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (7, '666', '源计划', 'https://img2.baidu.com/it/u=2016764601,1618302265&fm=253&fmt=auto&app=138&f=PNG');
INSERT INTO `test` (`id`, `name`, `description`, `image`) VALUES (8, '777', '未来战士', 'https://img0.baidu.com/it/u=718823970,501814686&fm=253&fmt=auto&app=138&f=PNG');
接口返回json结构数据。包含三个字段
image:图片真实地址
name:图片名称
description:图片描述
铸造NFT
1.调用setBaseUri方法,设置baseUri为盲盒图片
2.调用safeMint方法铸造nft
这里多创建几个
进入opensea测试网查看
可以看到nft盲盒如下
开启盲盒
调用setBlindBoxOpened方法开启盲盒
refresh metadata
可以看到所有图片都已经展示出来了。(两张图片依然为盲盒,是因为我铸造NFT的时候,图片就是盲盒图片,尴尬一下😓)