/
LazyMintWithTier.sol
129 lines (104 loc) · 5.04 KB
/
LazyMintWithTier.sol
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./interface/ILazyMintWithTier.sol";
import "../extension/BatchMintMetadata.sol";
library LazyMintWithTierStorage {
bytes32 public constant LAZY_MINT_WITH_TIER_STORAGE_POSITION = keccak256("lazy.mint.with.tier.storage");
struct Data {
/// @notice The tokenId assigned to the next new NFT to be lazy minted.
uint256 nextTokenIdToLazyMint;
/// @notice Mapping from a tier -> the token IDs grouped under that tier.
mapping(string => ILazyMintWithTier.TokenRange[]) tokensInTier;
/// @notice A list of tiers used in this contract.
string[] tiers;
}
function lazyMintWithTierStorage() internal pure returns (Data storage lazyMintWithTierData) {
bytes32 position = LAZY_MINT_WITH_TIER_STORAGE_POSITION;
assembly {
lazyMintWithTierData.slot := position
}
}
}
/**
* The `LazyMint` is a contract extension for any base NFT contract. It lets you 'lazy mint' any number of NFTs
* at once. Here, 'lazy mint' means defining the metadata for particular tokenIds of your NFT contract, without actually
* minting a non-zero balance of NFTs of those tokenIds.
*/
abstract contract LazyMintWithTier is ILazyMintWithTier, BatchMintMetadata {
function nextTokenIdToLazyMint() internal view returns (uint256) {
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
return data.nextTokenIdToLazyMint;
}
function tokensInTier(string memory _tier) internal view returns (TokenRange[] memory) {
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
return data.tokensInTier[_tier];
}
/**
* @notice Lets an authorized address lazy mint a given amount of NFTs.
*
* @param _amount The number of NFTs to lazy mint.
* @param _baseURIForTokens The base URI for the 'n' number of NFTs being lazy minted, where the metadata for each
* of those NFTs is `${baseURIForTokens}/${tokenId}`.
* @param _data Additional bytes data to be used at the discretion of the consumer of the contract.
* @return batchId A unique integer identifier for the batch of NFTs lazy minted together.
*/
function lazyMint(
uint256 _amount,
string calldata _baseURIForTokens,
string calldata _tier,
bytes calldata _data
) public virtual override returns (uint256 batchId) {
if (!_canLazyMint()) {
revert("Not authorized");
}
if (_amount == 0) {
revert("0 amt");
}
uint256 startId = nextTokenIdToLazyMint();
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
(data.nextTokenIdToLazyMint, batchId) = _batchMintMetadata(startId, _amount, _baseURIForTokens);
// Handle tier info.
if (!(data.tokensInTier[_tier].length > 0)) {
data.tiers.push(_tier);
}
data.tokensInTier[_tier].push(TokenRange(startId, batchId));
emit TokensLazyMinted(_tier, startId, startId + _amount - 1, _baseURIForTokens, _data);
return batchId;
}
/// @notice Returns all metadata lazy minted for the given tier.
function _getMetadataInTier(string memory _tier)
private
view
returns (TokenRange[] memory tokens, string[] memory baseURIs)
{
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
tokens = data.tokensInTier[_tier];
uint256 len = tokens.length;
baseURIs = new string[](len);
for (uint256 i = 0; i < len; i += 1) {
baseURIs[i] = _getBaseURI(tokens[i].startIdInclusive);
}
}
/// @notice Returns all metadata for all tiers created on the contract.
function getMetadataForAllTiers() external view returns (TierMetadata[] memory metadataForAllTiers) {
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
string[] memory allTiers = data.tiers;
uint256 len = allTiers.length;
metadataForAllTiers = new TierMetadata[](len);
for (uint256 i = 0; i < len; i += 1) {
(TokenRange[] memory tokens, string[] memory baseURIs) = _getMetadataInTier(allTiers[i]);
metadataForAllTiers[i] = TierMetadata(allTiers[i], tokens, baseURIs);
}
}
/**
* @notice Returns whether any metadata is lazy minted for the given tier.
*
* @param _tier We check whether this given tier is empty.
*/
function isTierEmpty(string memory _tier) internal view returns (bool) {
LazyMintWithTierStorage.Data storage data = LazyMintWithTierStorage.lazyMintWithTierStorage();
return data.tokensInTier[_tier].length == 0;
}
/// @dev Returns whether lazy minting can be performed in the given execution context.
function _canLazyMint() internal view virtual returns (bool);
}