Created
March 22, 2022 14:42
-
-
Save indiejoseph/9a37b96440ab3cf57206bfcee7c5c559 to your computer and use it in GitHub Desktop.
This file contains 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 "erc721a/contracts/ERC721A.sol"; | |
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
contract WEARKey is ERC721A, Ownable { | |
// events | |
event WhitelistMint(address sender, uint256 count); | |
event Mint(address sender, uint256 count); | |
event SetMerkleRoot(bytes32 merkleRoot); | |
event SetBaseURI(string baseURI); | |
event Pause(); | |
event Unpause(); | |
event ToggleSale(bool saleIsOpen); | |
event Withdraw(uint256 balance); | |
string public _baseTokenURI; | |
bool public saleIsOpen; | |
bool public paused; | |
bytes32 public merkleRoot; | |
mapping(address => uint256) public whitelistClaimed; | |
uint256 public constant MAX_ITEMS = 1000; | |
uint256 public constant basePrice = 0.35 ether; | |
uint256 public constant preSalePrice = 0.15 ether; | |
address public constant proxyRegistryAddress = 0xa5409ec958C83C3f309868babACA7c86DCB077c1; | |
uint256 public constant MAX_PER_USER = 15; | |
uint256 public constant MAX_PER_WHITELIST = 1; | |
modifier notPaused() { | |
if (_msgSender() != owner()) { | |
require(!paused, "Pausable: paused"); | |
} | |
_; | |
} | |
modifier onlySaleOpen() { | |
require(saleIsOpen, "Public sale is not started yet"); | |
_; | |
} | |
modifier onlyWhitelistedUser(bytes32[] calldata _merkleProof) { | |
bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); | |
require(whitelistClaimed[msg.sender] < MAX_PER_WHITELIST + 1, "Address has already claimed"); | |
require(MerkleProof.verify(_merkleProof, merkleRoot, leaf), "Invalid proof"); | |
_; | |
} | |
constructor(string memory baseTokenURI_) ERC721A("WEARKey", "WEARKEY") { | |
_baseTokenURI = baseTokenURI_; | |
} | |
function totalMint() public view returns (uint256) { | |
return totalSupply(); | |
} | |
function setMerkleRoot(bytes32 _merkleRoot) public onlyOwner { | |
emit SetMerkleRoot(_merkleRoot); | |
merkleRoot = _merkleRoot; | |
} | |
function _mint(uint256 _count) internal { | |
address _caller = _msgSender(); | |
require(_currentIndex + _count < MAX_ITEMS + 2, "Exceeds max supply"); | |
require( | |
balanceOf(msg.sender) + _count < MAX_PER_USER + 1, | |
"You are not allowed to mint this many!" | |
); | |
require(msg.value >= price(_count), "Value below price"); | |
require(_count > 0, "No 0 mints"); | |
require(tx.origin == _caller, "No contracts"); | |
_safeMint(_caller, _count); | |
} | |
function mint(uint256 _count) external payable onlySaleOpen notPaused { | |
_mint(_count); | |
emit Mint(_msgSender(), _count); | |
} | |
function whitelistMint(uint256 _count, bytes32[] calldata _merkleProof) | |
external | |
payable | |
notPaused | |
onlyWhitelistedUser(_merkleProof) | |
{ | |
_mint(_count); | |
emit WhitelistMint(_msgSender(), _count); | |
} | |
function price(uint256 _count) public view returns (uint256) { | |
if (saleIsOpen == false) { | |
// pre-sale price | |
return preSalePrice * _count; | |
} | |
return basePrice * _count; | |
} | |
function setBaseURI(string memory baseURI) public onlyOwner { | |
_baseTokenURI = baseURI; | |
emit SetBaseURI(baseURI); | |
} | |
// https://docs.opensea.io/docs/1-structuring-your-smart-contract#creature-erc721-contract | |
function baseTokenURI() public view returns (string memory) { | |
return _baseTokenURI; | |
} | |
// internal | |
function _baseURI() internal view virtual override returns (string memory) { | |
return _baseTokenURI; | |
} | |
function pause() public onlyOwner { | |
paused = true; | |
emit Pause(); | |
} | |
function unpause() public onlyOwner { | |
paused = false; | |
emit Unpause(); | |
} | |
function toggleSale() public onlyOwner { | |
saleIsOpen = !saleIsOpen; | |
emit ToggleSale(saleIsOpen); | |
} | |
function isApprovedForAll(address owner, address operator) public view override returns (bool) { | |
// Whitelist OpenSea proxy contract for easy trading. | |
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress); | |
if (address(proxyRegistry.proxies(owner)) == operator) { | |
return true; | |
} | |
return super.isApprovedForAll(owner, operator); | |
} | |
// widthdraw fund from the contract | |
function withdraw() public onlyOwner { | |
uint256 balance = address(this).balance; | |
require(balance > 0, "Balance is 0"); | |
(bool sent, ) = payable(owner()).call{value: balance}(""); | |
require(sent, "Failed to send Ether"); | |
emit Withdraw(balance); | |
} | |
function _startTokenId() internal view virtual override returns (uint256) { | |
return 1; | |
} | |
} | |
contract OwnableDelegateProxy {} | |
contract ProxyRegistry { | |
mapping(address => OwnableDelegateProxy) public proxies; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment