// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
interface IMerkleDistributor {
// function token() external view returns (address);
// Returns the merkle root of the merkle tree containing account balances available to claim.
function merkleRoot() external view returns (bytes32);
}
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol';
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol';
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol';
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract ETRY is IMerkleDistributor,ERC721, Ownable, ReentrancyGuard{
uint256 public constant MINT_PRICE = 70000000000000000;
uint public REMAINING_SUPPLY = 9224;
bool MINTING_ALLOWED = true;
bool PRESALE_ONLY = true;
uint PRESALE_TOKEN_MAXIMUM_AMOUNT = 10;
uint WALLET_TOKEN_MAXIMUM_AMOUNT = 10;
uint MINTING_STAGE = 1;
using Strings for uint256;
address FUNDS_RECIPIENT = 0x16583250954Ff09EF3adBa9Cc6c94d883D26465e;
//address public override token;
bytes32 public override merkleRoot;
// Optional mapping for token URIs
mapping (uint256 => string) private _tokenURIs;
mapping(uint256 => uint256) claimedMints;
// Base URI
string private _baseURIextended;
uint private counter = 0;
constructor( string memory _name, string memory _symbol, bytes32 merkleRoot_ )
ERC721(_name, _symbol){
merkleRoot = merkleRoot_;
}
function markMint(uint256 index, uint256 amount) internal{
if (claimedMints[index]!= 0){
claimedMints[index] = claimedMints[index] + amount;
} else {
claimedMints[index] = amount;
}
}
/*
* Stop minting. This function should just be used by the owner
*/
function stopMinting() public onlyOwner(){
MINTING_ALLOWED = false;
}
/*
* Start minting. This function should just be used by the owner
*/
function startMinting() public onlyOwner(){
MINTING_ALLOWED = true;
}
//Set the MerkleProofRoot
function changeMerkleProofRoot( bytes32 merkleRoot_ ) external onlyOwner() {
merkleRoot = merkleRoot_;
}
//Internal function to verify merkleProof
function verify(uint256 index, address account, uint stage, bytes32[] calldata merkleProof) internal {
// Verify the merkle proof.
bytes32 node = keccak256(abi.encodePacked(index, account, stage));
require(MerkleProof.verify(merkleProof, merkleRoot, node), 'MerkleDistributor: Invalid proof.');
}
function contractURI() public view returns (string memory) {
return _baseURI();
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseURIextended;
}
/*
* Owner can withdraw the contract's ETH to an external address
*/
function withdrawETH( address ethAddress, uint amount) public onlyOwner(){
payable(ethAddress).transfer(amount);
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(base, tokenId.toString()));
}
/*
* Mint function
*/
function mintByOwner(uint256 _amount,address recipient) public onlyOwner() {
uint index = counter;
uint lastIndex = counter + _amount;
for (uint _index = index;_index < lastIndex;_index++ ){
_mint(recipient, _index+1);
_setTokenURI(_index+1, Strings.toString(_index+1));
counter++;
REMAINING_SUPPLY--;
}
}
/*
* Mint function
*/
function mint(uint256 _amount, uint256 merketree_index,bytes32[] calldata merkleProof, uint stage) public payable nonReentrant() {
require(MINTING_ALLOWED, "Minting is not allowed");
require(_amount <= REMAINING_SUPPLY,"There are not this many tokens left");
require(_amount <= 10,"10 Tokens is the limit per transaction");
if (PRESALE_ONLY){
require(MINTING_STAGE >= stage, "Address not allowed in this stage");
verify(merketree_index,msg.sender, stage, merkleProof);
require(claimedMints[merketree_index]+_amount <=PRESALE_TOKEN_MAXIMUM_AMOUNT, "User already minted 10 times");
}
uint256 totalCost = getMintingCost(_amount);
require(msg.value >= totalCost,"Insufficient Gas.");
uint index = counter;
uint lastIndex = counter + _amount;
for (uint _index = index;_index < lastIndex;_index++ ){
_mint(msg.sender, _index+1);
_setTokenURI(_index+1, Strings.toString(_index+1));
counter++;
REMAINING_SUPPLY--;
}
if (PRESALE_ONLY){
markMint(merketree_index,_amount);
}
// payable(FUNDS_RECIPIENT).send(totalCost);
// send the funds
}
//Return minting cost
function getMintingCost(uint totalItems)
private
pure
returns (uint256)
{
return totalItems * MINT_PRICE;
}
function totalTokensMinted() public view returns(uint){
return counter;
}
function totalSupply() public view returns(uint){
return 9224;
}
function preSaleFlag() public view returns(bool){
return PRESALE_ONLY;
}
function enablePresale() external onlyOwner() {
PRESALE_ONLY = true;
}
function disablePresale() external onlyOwner() {
PRESALE_ONLY = false;
}
function setMintingStage(uint stage) external onlyOwner() {
MINTING_STAGE = stage;
}
function remainingSupply() public view returns(uint){
return REMAINING_SUPPLY;
}
//Set the Base URI
function setBaseURI(string memory baseURI_) external onlyOwner() {
_baseURIextended = baseURI_;
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Trees proofs.
*
* The proofs can be generated using the JavaScript library
* https://github.com/miguelmota/merkletreejs[merkletreejs].
* Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
*
* See `test/utils/cryptography/MerkleProof.test.js` for some examples.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == root;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/EternalRoyals.sol": "ETRY"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REMAINING_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"name":"changeMerkleProofRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disablePresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enablePresale","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":"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":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"merketree_index","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"stage","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"preSaleFlag","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remainingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stage","type":"uint256"}],"name":"setMintingStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopMinting","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":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensMinted","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"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ethAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]