-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path721ANFT.sol
189 lines (151 loc) · 5.53 KB
/
721ANFT.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Smart Contract Developed By Robert McMenemy
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "ERC721A/ERC721A.sol";
contract MYNft is ERC721A, Ownable, ReentrancyGuard {
using Strings for uint256;
using MerkleProof for bytes32[];
enum MintState {
Stopped,
Public,
Private
}
uint256 private immutable MAX_SUPPLY = 4500;
uint256 private immutable MAX_PER_WALLET = 3;
uint256 public privateCost = 0.0001 ether;
uint256 public cost = 0.001 ether;
bool public revealedState = false;
MintState public mintState;
string private __baseURI;
string private _notRevealedURI;
bytes32 private _presaleMerkleRoot;
bytes32 private _ogMerkleRoot;
bool public devMintLocked;
constructor(string memory initBaseURI_, string memory initNotRevealedURI_, bytes32 presaleRoot_)
ERC721A("MyNft", "MNFT")
Ownable()
checkURI(initBaseURI_)
checkURI(initNotRevealedURI_)
{
require(presaleRoot_ != bytes32(0), "[Error] Empty Root");
__baseURI = initBaseURI_;
_notRevealedURI = initNotRevealedURI_;
_presaleMerkleRoot = presaleRoot_;
// Initialize mint state
mintState = MintState.Stopped;
}
modifier checkURI(string memory str) {
require(bytes(str).length > 0, "[Error] URI Cannot Be Blank");
_;
}
modifier maxWalletCheck(uint256 quantity) {
require(uint256(_numberMinted(msg.sender)) + quantity <= MAX_PER_WALLET, "[Error] Max Per Wallet Reached");
_;
}
modifier supplyCheck(uint256 quantity) {
require(_totalMinted() + quantity <= MAX_SUPPLY, "[Error] Max Mint Reached");
_;
}
modifier checkWhitelisted(bytes32[] memory proof, bytes32 root) {
require(proof.verify(_presaleMerkleRoot, keccak256(abi.encodePacked(msg.sender))), "[Error] Not whitelisted");
_;
}
modifier checkCost(uint256 totalCost, uint256 quantity) {
require(msg.value >= totalCost * quantity, "[Error] Not enough funds supplied");
_;
}
modifier checkValue(uint256 value) {
require(value > 0, "[Error] Value cannot be 0");
_;
}
function privateMint(bytes32[] memory proof, uint8 quantity)
external
payable
maxWalletCheck(quantity)
supplyCheck(quantity)
checkWhitelisted(proof, _presaleMerkleRoot)
checkCost(privateCost, quantity)
nonReentrant
{
require(mintState == MintState.Private, "[Error] Private Mint Not Started");
_mint(msg.sender, quantity);
_sendFunds(msg.value);
}
function mint(uint8 quantity)
external
payable
maxWalletCheck(quantity)
supplyCheck(quantity)
checkCost(cost, quantity)
nonReentrant
{
require(mintState == MintState.Public, "[Error] Public Mint Not Started");
_mint(msg.sender, quantity);
_sendFunds(msg.value);
}
function _startTokenId() internal view virtual override returns (uint256) {
return 1;
}
function _baseURI() internal view virtual override returns (string memory) {
return __baseURI;
}
function tokenURI(uint256 tokenId) public view virtual override(ERC721A) returns (string memory) {
string memory currentUri = (revealedState == true) ? __baseURI : _notRevealedURI;
return bytes(currentUri).length > 0 ? string(abi.encodePacked(currentUri, tokenId.toString(), ".json")) : "";
}
function lockDevMint() external onlyOwner {
devMintLocked = true;
}
function devMint(uint8 quantity) external onlyOwner supplyCheck(quantity) {
require(devMintLocked == false, "[Error] Locked");
_mint(msg.sender, quantity);
}
function stopMint() external onlyOwner {
mintState = MintState.Stopped;
}
function turnOnPublicMint() external onlyOwner {
mintState = MintState.Public;
}
function turnOnPrivateMint() external onlyOwner {
mintState = MintState.Private;
}
function toggleReveal() external onlyOwner {
revealedState = !revealedState;
}
function setMerkleRoot(bytes32 root) external onlyOwner {
require(root.length > 0, "[Error] Empty Root");
_presaleMerkleRoot = root;
}
function setPublicMintPrice(uint256 value) external onlyOwner checkValue(value) {
cost = value;
}
function setPrivateMintPrice(uint256 value) external onlyOwner checkValue(value) {
privateCost = value;
}
function setBaseURI(string memory newBaseURI) external onlyOwner nonReentrant checkURI(newBaseURI) {
__baseURI = newBaseURI;
}
function setNotRevealedURI(string memory newNotRevealedURI)
external
onlyOwner
nonReentrant
checkURI(newNotRevealedURI)
{
_notRevealedURI = newNotRevealedURI;
}
function withdraw() external onlyOwner nonReentrant {
sendFunds(address(this).balance);
}
function sendFunds(uint256 _totalAmount) internal {
address(owner()).transfer(_totalAmount);
}
// Including the _safeTransferETH function for completeness
function _safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}("");
require(success, "[Error] ETH Transfer Failed");
}
}