有关盲盒的区块链智能合约实现

122 阅读2分钟

好几个月没有更新了相关内容了,之前跟炜哥聊到合约实现各种功能的时候,还催我把 《怎样写出Axie Infinity的合约(一)》 这个系列更完,但是真的是没时间。不过之前也正好聊到盲盒相关的问题了,可能关于上链后更改状态不熟悉区块链的朋友会有疑问,但其实实现起来挺简单的,趁这个机会也更个文章吧。

目前能想到的有两种实现方式,一种比较灵活:直接修改tokenURI,即暴露一个方法给授权地址,在需要的时候可以修改tokenURI;一种比较简洁:设置一个变量作为开关,被授权的地址调用方法来切换不同的tokenURI。

那么有没有既灵活又简洁的方法呢?把两种方式加起来就好了(对不起,抖了个机灵)……即开启盲盒的时候,既改变开关变量(这个是为了在其他相关逻辑中方便的获取到开启状态),同时也要设置tokenURI。

上代码:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// contracts/test.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC721, ERC721URIStorage, Ownable {
constructor() ERC721("MyToken", "MTK") {}

string private _tokenURIPrefix = "https://some.storage.online/opened/";
string private _tokenURISuffix = ".json";
bool private _mysteryBoxOpened = false;
string private _mysteryTokenURI = "https://some.storage.online/mystery/token.png";

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

function isMysteryBoxOpened() public view returns (bool) {
return _mysteryBoxOpened;
}

function setMysteryBoxStatus(bool _status, string memory _baseUrl) external onlyOwner {
_mysteryBoxOpened= _status;
//如果_baseUrl传入空字符串'',则不会改变原有的路径前缀
if(bytes(_baseUrl).length > 0) _tokenURIPrefix = _baseUrl;
}

function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
if (_mysteryBoxOpened) {
return
string(
//最近查阅到有abi.encodePacked的方法可以用,非常方便
//以前参考使用axie的代码,组装起来很复杂
abi.encodePacked(_tokenURIPrefix, Strings.toString(tokenId), _tokenURISuffix)
);
} else {
return _mysteryTokenURI;
}
}
}

就酱紫。

[2022年03月08日原始发布于本作者博客]

查看原文: www.gsgundam.com/archive/202…