-
Notifications
You must be signed in to change notification settings - Fork 6
/
SequentialMintCollection.sol
124 lines (104 loc) · 4.38 KB
/
SequentialMintCollection.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
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.12;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "../../interfaces/ITokenCreator.sol";
/**
* @title Extends the OZ ERC721 implementation for collections which mint sequential token IDs.
*/
abstract contract SequentialMintCollection is ITokenCreator, Initializable, ERC721BurnableUpgradeable {
/****** Slot 0 (after inheritance) ******/
/**
* @notice The creator/owner of this NFT collection.
* @dev This is the default royalty recipient if an different `paymentAddress` was not provided.
* @return The collection's creator/owner address.
*/
address payable public owner;
/**
* @notice The tokenId of the most recently created NFT.
* @dev Minting starts at tokenId 1. Each mint will use this value + 1.
* @return The most recently minted tokenId, or 0 if no NFTs have been minted yet.
*/
uint32 public latestTokenId;
/**
* @notice The max tokenId which can be minted.
* @dev This max may be less than the final `totalSupply` if 1 or more tokens were burned.
* @return The max tokenId which can be minted.
*/
uint32 public maxTokenId;
/**
* @notice Tracks how many tokens have been burned.
* @dev This number is used to calculate the total supply efficiently.
*/
uint32 private burnCounter;
/****** End of storage ******/
/**
* @notice Emitted when the max tokenId supported by this collection is updated.
* @param maxTokenId The new max tokenId. All NFTs in this collection will have a tokenId less than
* or equal to this value.
*/
event MaxTokenIdUpdated(uint256 indexed maxTokenId);
/**
* @notice Emitted when this collection is self destructed by the creator/owner/admin.
* @param admin The account which requested this contract be self destructed.
*/
event SelfDestruct(address indexed admin);
modifier onlyCreator() {
require(msg.sender == owner, "SequentialMintCollection: Caller is not creator");
_;
}
function _initializeSequentialMintCollection(address payable _creator, uint32 _maxTokenId) internal onlyInitializing {
require(_creator != address(0), "SequentialMintCollection: Creator cannot be the zero address");
owner = _creator;
maxTokenId = _maxTokenId;
}
/**
* @notice Allows the collection owner to destroy this contract only if
* no NFTs have been minted yet or the minted NFTs have been burned.
*/
function _selfDestruct() internal {
require(totalSupply() == 0, "SequentialMintCollection: Any NFTs minted must be burned first");
emit SelfDestruct(msg.sender);
selfdestruct(payable(msg.sender));
}
/**
* @notice Allows the owner to set a max tokenID.
* This provides a guarantee to collectors about the limit of this collection contract, if applicable.
* @dev Once this value has been set, it may be decreased but can never be increased.
* @param _maxTokenId The max tokenId to set, all NFTs must have a tokenId less than or equal to this value.
*/
function _updateMaxTokenId(uint32 _maxTokenId) internal {
require(_maxTokenId != 0, "SequentialMintCollection: Max token ID may not be cleared");
require(maxTokenId == 0 || _maxTokenId < maxTokenId, "SequentialMintCollection: Max token ID may not increase");
require(latestTokenId <= _maxTokenId, "SequentialMintCollection: Max token ID must be >= last mint");
maxTokenId = _maxTokenId;
emit MaxTokenIdUpdated(_maxTokenId);
}
function _burn(uint256 tokenId) internal virtual override {
unchecked {
// Number of burned tokens cannot exceed latestTokenId which is the same size.
++burnCounter;
}
super._burn(tokenId);
}
/**
* @inheritdoc ITokenCreator
* @dev The tokenId param is ignored since all NFTs return the same value.
*/
function tokenCreator(
uint256 /* tokenId */
) external view returns (address payable creator) {
creator = owner;
}
/**
* @notice Returns the total amount of tokens stored by the contract.
* @dev From the ERC-721 enumerable standard.
* @return supply The total number of NFTs tracked by this contract.
*/
function totalSupply() public view returns (uint256 supply) {
unchecked {
// Number of tokens minted is always >= burned tokens.
supply = latestTokenId - burnCounter;
}
}
}