18.03
($-0.28%)
| 1 Gwei
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@thirdweb-dev/contracts/extension/Ownable.sol"; import "@thirdweb-dev/contracts/extension/ContractMetadata.sol"; import "@thirdweb-dev/contracts/extension/Multicall.sol"; import "@thirdweb-dev/contracts/extension/PrimarySale.sol"; import "@thirdweb-dev/contracts/extension/DefaultOperatorFilterer.sol"; import "@thirdweb-dev/contracts/lib/TWStrings.sol"; import "@thirdweb-dev/contracts/lib/CurrencyTransferLib.sol"; import "./ERC721R.sol"; import "./ERC721REnumerable.sol"; import "./ERC721URIStorage.sol"; /** * @dev etcher.etc: Implementation of ERC721 Non-Fungible Token Standard with new features, * Including safu random batch minting and burning rewards mechanics, updated Enumerable and URI Storage. * Created special for ETC MostWanted #ETCMW * website: etcmw.org */ contract Etcmw is ERC721r, ERC721rEnumerable, Ownable, ContractMetadata, Multicall, PrimarySale, DefaultOperatorFilterer, ERC721URIStorage { string public baseUri = "ipfs://Qmf7GAcUt3MWsCPh6wjdz3z8WfqJix947A3hF2enTf4Dyo/"; string public baseExtension = ".json"; bool public isMintingEnabled = true; uint256 private constant max_Supply = 10000; uint256 private constant maxTxMints = 10; uint256 private constant priceA = 1 ether; //phase 1 uint256 private constant priceB = 2 ether; //phase 2 uint256 private constant priceC = 3 ether; //phase 3 uint256 private constant rwrdA = 0; //phase 1 uint256 private constant rwrdB = 0.5 ether; //phase 2 uint256 private constant rwrdC = 1 ether; //phase 3++ uint256 private constant phase1 = 1000; //items uint256 private constant phase2 = 5000; //items. phase 3 items = max - (phase 1 + phase 2) // Common - 0 //default // Miner - 1 // Investor - 2 // Dev - 3 enum Role { Common, Miner, Investor, Dev } // we use index as token id. Id's starting from 0 Role[] private _tokensRole; constructor( address _defaultAdmin, string memory _name, string memory _symbol, string memory _contractURI, address _primarySaleRecipient ) ERC721r(_name, _symbol, max_Supply) { _setupOwner(_defaultAdmin); _setupContractURI(_contractURI); _setupPrimarySaleRecipient(_primarySaleRecipient); _setOperatorRestriction(true); } using TWStrings for uint256; using SafeMath for uint256; receive() external payable {} function tokenURI( uint256 tokenId ) public view virtual override(ERC721r, ERC721URIStorage) returns (string memory) { require( _exists(tokenId), "ERC721Metadata: URI query for nonexistent token" ); string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string( abi.encodePacked( currentBaseURI, tokenId.toString(), baseExtension ) ) : ""; } function _baseURI() internal view virtual override returns (string memory) { return baseUri; } function setBaseURI(string memory newBaseURI) public onlyOwner { require(bytes(newBaseURI).length > 0, "Base URI cannot be empty"); baseUri = newBaseURI; } function setTokenURI(uint256 tokenId, string memory uri) public onlyOwner { require(_exists(tokenId), "Token ID does not exist"); _setTokenURI(tokenId, uri); } function stopmint() public onlyOwner { isMintingEnabled = false; } function enablemint() public onlyOwner { isMintingEnabled = true; } function totalMinted() public view returns (uint256) { require(_availableToMint() <= _maxSupply, "caught up"); return _maxSupply - _availableToMint(); } function getPrice() public view returns (uint256) { if (totalMinted() >= phase1 && totalMinted() < phase2) return priceB; if (totalMinted() >= phase2) return priceC; return priceA; } function getBurnRwd() public view returns (uint256) { if (totalMinted() >= phase1 && totalMinted() < phase2) return rwrdB; if (totalMinted() >= phase2) return rwrdC; return rwrdA; } function getBatchPrice(uint256 amount) public view returns (uint256) { require(totalMinted() + amount <= max_Supply, "caught up"); require(amount <= maxTxMints, "caught up"); return amount.mul(getPrice()); //if totalMinted < next phase && totalMinted + amount > next phase its ok to let mint some items without price increase(max amount 10 and it can only happen twice). This is preferable to overcomplicating the minting calculations } function _beforeTokenTransfer( address from, address to, uint256[] memory tokenIdxs ) internal virtual override(ERC721r, ERC721rEnumerable) { ERC721rEnumerable._beforeTokenTransfer(from, to, tokenIdxs); } function totalSupply() public view override(ERC721r, ERC721rEnumerable) returns (uint256) { return ERC721rEnumerable.totalSupply(); } /// @dev See ERC165: https://eips.ethereum.org/EIPS/eip-165 function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC721r, ERC721rEnumerable) returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f || // ERC165 Interface ID for ERC721Metadata interfaceId == 0x780e9d63; // ERC721Enumerable } /** * @dev Release etc to saleRecipient */ function release(uint256 totalAmount) external onlyOwner { address payable saleRecipient = payable(primarySaleRecipient()); uint256 balance = address(this).balance; require(balance >= totalAmount, "Insufficient balance"); CurrencyTransferLib.transferCurrency( CurrencyTransferLib.NATIVE_TOKEN, address(this), saleRecipient, totalAmount ); } function mint(uint256 quantity) external payable mintingEnabled { require(quantity <= maxTxMints, "caught up"); require(quantity <= _availableToMint(), "caught up"); require(quantity > 0, "caught up"); uint256 totalPrice = getBatchPrice(quantity); bool validMsgValue = msg.value == totalPrice; require(validMsgValue, "Invalid msg value"); address payable saleRecipient = payable(primarySaleRecipient()); _mintRandom(msg.sender, quantity); CurrencyTransferLib.transferCurrency( CurrencyTransferLib.NATIVE_TOKEN, msg.sender, saleRecipient, totalPrice / 2 ); CurrencyTransferLib.transferCurrency( CurrencyTransferLib.NATIVE_TOKEN, msg.sender, address(this), totalPrice / 2 ); } function _burn( uint256 tokenId ) internal override(ERC721r, ERC721URIStorage) { ERC721r._burn(tokenId); } function burn(uint256 tokenId) external { require(_exists(tokenId), "Not exists"); address payable owner = payable(ERC721r.ownerOf(tokenId)); uint256 rwrd = getBurnRwd(); uint256 balance = address(this).balance; require(_msgSender() == tx.origin, "Contracts cannot burn"); require(_msgSender() == owner, "Not owner"); _burn(tokenId); if (rwrd > 0 && balance >= rwrd) { CurrencyTransferLib.transferCurrency( CurrencyTransferLib.NATIVE_TOKEN, address(this), owner, rwrd ); } } modifier mintingEnabled() { require(isMintingEnabled, "Minting disabled"); _; } function getTokenRole( uint256 tokenId ) public view virtual returns (string memory) { require(_exists(tokenId), "Query for nonexistent token"); if (_tokensRole[tokenId] == Role.Investor) return "Investor"; if (_tokensRole[tokenId] == Role.Miner) return "Miner"; if (_tokensRole[tokenId] == Role.Dev) return "Dev"; return "Common"; } function initTokensRole(Role[] memory tokensRole) public onlyOwner { require(tokensRole.length == max_Supply, "require max supply length"); _tokensRole = tokensRole; } /// @dev Checks whether owner can be set in the given execution context. function _canSetOwner() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Checks whether contract metadata can be set in the given execution context. function _canSetContractURI() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Checks whether primary sale recipient can be set in the given execution context. function _canSetPrimarySaleRecipient() internal view virtual override returns (bool) { return msg.sender == owner(); } /// @dev Returns whether operator restriction can be set in the given execution context. function _canSetOperatorRestriction() internal virtual override returns (bool) { return msg.sender == owner(); } }
[{"inputs":[{"internalType":"address","name":"_defaultAdmin","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_contractURI","type":"string"},{"internalType":"address","name":"_primarySaleRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"restriction","type":"bool"}],"name":"OperatorRestriction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"PrimarySaleRecipientUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enablemint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getBatchPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBurnRwd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenRole","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Etcmw.Role[]","name":"tokensRole","type":"uint8[]"}],"name":"initTokensRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorRestriction","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"primarySaleRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_restriction","type":"bool"}],"name":"setOperatorRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_saleRecipient","type":"address"}],"name":"setPrimarySaleRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopmint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subscription","type":"address"}],"name":"subscribeToRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]