-
-
Save itsanishjain/b40263e5c2a85a53099e60db85bcf2a9 to your computer and use it in GitHub Desktop.
MiladyRaveMaker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.4; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "erc721a/contracts/ERC721A.sol"; | |
import "erc721a/contracts/extensions/ERC721AQueryable.sol"; | |
import "solady/src/Milady.sol"; | |
import "solady/src/utils/ECDSA.sol"; | |
import "solady/src/utils/LibString.sol"; | |
import "solady/src/utils/SafeTransferLib.sol"; | |
contract MiladyRaveMaker is ERC721A, ERC721AQueryable, Ownable { | |
using ECDSA for bytes32; | |
uint256 public constant PRICE_UNIT = 0.001 ether; | |
string private _tokenURI; | |
address public signer; | |
uint16 public maxSupply; | |
uint16 private _miladyPriceUnits; | |
uint16 private _publicPriceUnits; | |
bool public paused; | |
bool public mintLocked; | |
bool public maxSupplyLocked; | |
bool public tokenURILocked; | |
constructor() ERC721A("MiladyRave", "MIR") { | |
maxSupply = 5000; | |
_miladyPriceUnits = _toPriceUnits(0.03 ether); | |
_publicPriceUnits = _toPriceUnits(0.06 ether); | |
paused = true; // Must be initialized to true. | |
} | |
function _startTokenId() internal view virtual override returns (uint256) { | |
return 1; | |
} | |
function tokenURI(uint256 tokenId) public view override returns (string memory) { | |
return LibString.replace(_tokenURI, "{id}", _toString(tokenId)); | |
} | |
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | |
/* MINTING FUNCTIONS */ | |
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | |
function publicMint(uint256 quantity) external payable { | |
require(paused == false, "Paused."); | |
unchecked { | |
require(quantity <= 100, "Quantity too high."); | |
require(msg.value == _toPrice(_publicPriceUnits) * quantity, "Wrong Ether value."); | |
} | |
_requireMintable(quantity); | |
_mint(msg.sender, quantity); | |
} | |
function miladyMint(uint256 quantity, bytes calldata signature) external payable { | |
require(paused == false, "Paused."); | |
require( | |
keccak256(abi.encode(msg.sender)).toEthSignedMessageHash().recover(signature) == signer, | |
"Invalid signature." | |
); | |
unchecked { | |
require(quantity <= 100, "Quantity too high."); | |
require(msg.value == _toPrice(_miladyPriceUnits) * quantity, "Wrong Ether value."); | |
} | |
_requireMintable(quantity); | |
_mint(msg.sender, quantity); | |
} | |
function claimGiveaway(bytes calldata signature) external payable { | |
require(paused == false, "Paused."); | |
require( | |
keccak256(abi.encode(msg.sender)).toEthSignedMessageHash().recover(signature) == signer, | |
"Invalid signature." | |
); | |
require(_getAux(msg.sender) == 0, "Already claimed."); | |
_setAux(msg.sender, 1); | |
_requireMintable(1); | |
_mint(msg.sender, 1); | |
} | |
function hasClaimedGiveaway(address claimer) external view returns (bool) { | |
return _getAux(claimer) != 0; | |
} | |
function miladyPrice() external view returns (uint256) { | |
return _toPrice(_miladyPriceUnits); | |
} | |
function publicPrice() external view returns (uint256) { | |
return _toPrice(_publicPriceUnits); | |
} | |
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | |
/* PRIVATE HELPER FUNCTIONS */ | |
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | |
function _toPriceUnits(uint256 price) private pure returns (uint16) { | |
unchecked { | |
require(price % PRICE_UNIT == 0, "Price must be a multiple of PRICE_UNIT."); | |
require((price /= PRICE_UNIT) <= type(uint16).max, "Overflow."); | |
return uint16(price); | |
} | |
} | |
function _toPrice(uint16 priceUnits) private pure returns (uint256) { | |
return uint256(priceUnits) * PRICE_UNIT; | |
} | |
function _requireMintable(uint256 quantity) private view { | |
unchecked { | |
require(mintLocked == false, "Locked."); | |
require(_totalMinted() + quantity <= maxSupply, "Out of stock!"); | |
} | |
} | |
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | |
/* ADMIN FUNCTIONS */ | |
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | |
function forceMint(address[] calldata to, uint256 quantity) external onlyOwner { | |
_requireMintable(quantity * to.length); | |
unchecked { | |
for (uint256 i; i != to.length; ++i) { | |
_mint(to[i], quantity); | |
} | |
} | |
} | |
function selfMint(uint256 quantity) external onlyOwner { | |
_requireMintable(quantity); | |
unchecked { | |
uint256 miniBatchSize = 8; | |
uint256 i = quantity % miniBatchSize; | |
_mint(msg.sender, i); | |
while (i != quantity) { | |
_mint(msg.sender, miniBatchSize); | |
i += miniBatchSize; | |
} | |
} | |
} | |
function setTokenURI(string calldata value) external onlyOwner { | |
require(tokenURILocked == false, "Locked."); | |
_tokenURI = value; | |
} | |
function setMaxSupply(uint16 value) external onlyOwner { | |
require(maxSupplyLocked == false, "Locked."); | |
maxSupply = value; | |
} | |
function setPaused(bool value) external onlyOwner { | |
if (value == false) { | |
require(maxSupply != 0, "Max supply not set."); | |
require(signer != address(0), "Signer not set."); | |
} | |
paused = value; | |
} | |
function setSigner(address value) external onlyOwner { | |
require(value != address(0), "Signer must not be the zero address."); | |
signer = value; | |
} | |
function lockMint() external onlyOwner { | |
mintLocked = true; | |
} | |
function lockMaxSupply() external onlyOwner { | |
maxSupplyLocked = true; | |
} | |
function lockTokenURI() external onlyOwner { | |
tokenURILocked = true; | |
} | |
function setMiladyPrice(uint256 value) external onlyOwner { | |
_miladyPriceUnits = _toPriceUnits(value); | |
} | |
function setPublicPrice(uint256 value) external onlyOwner { | |
_publicPriceUnits = _toPriceUnits(value); | |
} | |
function withdraw() external payable onlyOwner { | |
SafeTransferLib.safeTransferETH(msg.sender, address(this).balance); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment