// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
/**
* @dev Interface module which provides a basic access control mechanism of the NFT Delegation Smart Contract
*/
interface IDelegationManagementContract {
/**
* @notice Returns an array of all delegation addresses (active AND inactive) assigned by a delegator for a specific use case on a specific NFT collection
*/
function retrieveDelegationAddresses(address _delegatorAddress, address _collectionAddress, uint256 _useCase) external view returns (address[] memory);
/**
* @notice Returns an array of all delegators (active AND inactive) that delegated to a delegationAddress for a specific use case on a specific NFT collection
*/
function retrieveDelegators(address _delegationAddress, address _collectionAddress, uint256 _useCase) external view returns (address[] memory);
/**
* @notice Returns an array of all active delegators on a certain date for a specific use case on a specific NFT collection given a delegation Address
*/
function retrieveActiveDelegators(address _delegationAddress, address _collectionAddress, uint256 _date, uint256 _useCase) external view returns (address[] memory);
/**
* @notice Returns the most recent delegation address delegated for a specific use case on a specific NFT collection
*/
function retrieveMostRecentDelegation(address _delegatorAddress, address _collectionAddress, uint256 _useCase) external view returns (address);
/**
* @notice Returns the most recent delegator for a specific use case on a specific NFT collection given a delegation Address
*/
function retrieveMostRecentDelegator(address _delegationAddress, address _collectionAddress, uint256 _useCase) external view returns (address);
/**
* @notice Returns the status of a delegation given the delegator address as well as the delegation address
*/
function retrieveGlobalStatusOfDelegation(address _delegatorAddress, address _collectionAddress, address _delegationAddress, uint256 _useCase) external view returns (bool);
/**
* @notice Returns the status of a delegation given the delegator address, the collection address, the delegation address as well as a specific token id
*/
function retrieveTokenStatus(address _delegatorAddress, address _collectionAddress, address _delegationAddress, uint256 _useCase, uint256 _tokenId) external view returns (bool);
/**
* @notice Checks if the delegation address performing actions is the most recent delegated by the specific delegator
*/
function retrieveStatusOfMostRecentDelegation(address _delegatorAddress, address _collectionAddress, address _delegationAddress, uint256 _useCase) external view returns (bool);
/**
* @notice Checks if a delegator granted subdelegation status to an Address
*/
function retrieveSubDelegationStatus(address _delegatorAddress, address _collectionAddress, address _delegationAddress) external view returns (bool);
/**
* @notice Checks the status of an active delegator for a delegation Address
*/
function retrieveStatusOfActiveDelegator(address _delegatorAddress, address _collectionAddress, address _delegationAddress, uint256 _date, uint256 _useCase) external view returns (bool);
/**
* @notice This function checks the Consolidation status between 2 addresses
*/
function checkConsolidationStatus(address _wallet1, address _wallet2, address _collectionAddress) external view returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
import "./IERC165.sol";
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface INextGenAdmins {
// retrieve global admin
function retrieveGlobalAdmin(address _address) external view returns(bool);
// retrieve function admin
function retrieveFunctionAdmin(address _address, bytes4 _selector) external view returns(bool);
// retrieve collection admin
function retrieveCollectionAdmin(address _address, uint256 _collectionID) external view returns(bool);
// retrieve if the contract is admin contract
function isAdminContract() external view returns (bool);
// retrieve owner
function owner() external view returns (address);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface INextGenCore {
function retrievewereDataAdded(uint256 _collectionID) external view returns(bool);
function viewTokensIndexMin(uint256 _collectionID) external view returns (uint256);
function viewTokensIndexMax(uint256 _collectionID) external view returns (uint256);
function viewCirSupply(uint256 _collectionID) external view returns (uint256);
function airDropTokens(uint256 mintIndex, address _recipient, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID) external;
function mint(uint256 mintIndex, address _mintingAddress , address _mintTo, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint256 phase) external;
function collectionFreezeStatus(uint256 _collectionID) external view returns(bool);
function viewMaxAllowance(uint256 _collectionID) external view returns (uint256);
function retrieveTokensMintedALPerAddress(uint256 _collectionID, address _address) external view returns(uint256);
function retrieveTokensMintedPublicPerAddress(uint256 _collectionID, address _address) external view returns(uint256);
function viewColIDforTokenID(uint256 _tokenid) external view returns (uint256);
function burnToMint(uint256 mintIndex, uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o, address burner) external;
function retrieveArtistAddress(uint256 _collectionID) external view returns(address);
function setTokenHash(uint256 _collectionID, uint256 _mintIndex, bytes32 _hash) external;
function retrieveTokenHash(uint256 _tokenid) external view returns(bytes32);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.18;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates merkle trees that are safe
* against this attack out of the box.
*/
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) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*
* _Available since v4.7._
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* _Available since v4.7._
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
// SPDX-License-Identifier: MIT
/**
*
* @title: NextGen 6529 - Minter Contract
* @date: 20-December-2023
* @version: 1.10
* @author: 6529 team
*/
pragma solidity ^0.8.19;
import "./INextGenCore.sol";
import "./IDelegationManagementContract.sol";
import "./MerkleProof.sol";
import "./INextGenAdmins.sol";
import "./IERC721.sol";
contract NextGenMinterContract {
// total funds collected during minting per collection
mapping (uint256 => uint256) public collectionTotalAmount;
// timestamp of last mint for used in sales model 3
mapping (uint256 => uint) public lastMintDate;
// tokens airdropped per collection
mapping (uint256 => uint256) public excludeTokensCounter;
// burn or swap address during burnOrSwap functionality
mapping (bytes32 => address) public burnOrSwapAddress;
// token ids set during burnOrSwap functionality
mapping (bytes32 => uint256[2]) private burnOrSwapIds;
// burnToMint initialization --> burn a token on a NextGen collection and mint a token on a new NextGen collection
mapping (uint256 => mapping (uint256 => bool)) public burnToMintCollections;
// burnOrSwap initialization --> burn a token on an external ERC721 collection and mint a token on a NextGen collection
mapping (bytes32 => mapping (uint256 => bool)) public burnExternalToMintCollections;
// checks if minting costs for a collectionwere set
mapping (uint256 => bool) private setMintingCosts;
// struct that holds minting costs and phases
struct collectionPhasesDataStructure {
uint allowlistStartTime;
uint allowlistEndTime;
uint publicStartTime;
uint publicEndTime;
bytes32 merkleRoot;
uint256 collectionMintCost;
uint256 collectionEndMintCost;
uint256 timePeriod;
uint256 rate;
uint8 salesOption;
address delAddress;
}
// mapping of collectionPhasesData struct
mapping (uint256 => collectionPhasesDataStructure) private collectionPhases;
// struct that holds primary royalties
struct royaltiesPrimarySplits {
uint256 artistPercentage;
uint256 teamPercentage;
}
// mapping of royaltiesPrimarySplits struct
mapping (uint256 => royaltiesPrimarySplits) private collectionRoyaltiesPrimarySplits;
// struct that holds addresses and percentages for primary splits
struct collectionPrimaryAddresses {
address primaryAdd1;
address primaryAdd2;
address primaryAdd3;
uint256 add1Percentage;
uint256 add2Percentage;
uint256 add3Percentage;
bool setStatus;
bool approvedStatus;
}
// mapping of collectionPrimaryAndSecondaryAddresses struct
mapping (uint256 => collectionPrimaryAddresses) private collectionArtistPrimaryAddresses;
// struct that holds secondary royalties
struct royaltiesSecondarySplits {
uint256 artistPercentage;
uint256 teamPercentage;
}
// mapping of royaltiesSecondarySplits struct
mapping (uint256 => royaltiesSecondarySplits) private collectionRoyaltiesSecondarySplits;
// struct that holds addresses and percentages for secondary splits
struct collectionSecondaryAddresses {
address secondaryAdd1;
address secondaryAdd2;
address secondaryAdd3;
uint256 add1Percentage;
uint256 add2Percentage;
uint256 add3Percentage;
bool setStatus;
bool approvedStatus;
}
// mapping of collectionSecondaryAddresses struct
mapping (uint256 => collectionSecondaryAddresses) private collectionArtistSecondaryAddresses;
// mapping that holds the auction end time when a token is sent to auction
mapping (uint256 => uint) private mintToAuctionData;
// mapping that holds the auction status when a token is sent to auction
mapping (uint256 => bool) private mintToAuctionStatus;
//external contracts declaration
INextGenCore public gencore;
IDelegationManagementContract public dmc;
INextGenAdmins private adminsContract;
// events
event Withdraw(address indexed _add, bool status, uint256 indexed funds);
// constructor
constructor (address _gencore, address _del, address _adminsContract) {
gencore = INextGenCore(_gencore);
dmc = IDelegationManagementContract(_del);
adminsContract = INextGenAdmins(_adminsContract);
}
// certain functions can only be called by an admin or the artist
modifier ArtistOrAdminRequired(uint256 _collectionID, bytes4 _selector) {
require(msg.sender == gencore.retrieveArtistAddress(_collectionID) || adminsContract.retrieveFunctionAdmin(msg.sender, _selector) == true || adminsContract.retrieveGlobalAdmin(msg.sender) == true, "Not allowed");
_;
}
// certain functions can only be called by a global or function admin
modifier FunctionAdminRequired(bytes4 _selector) {
require(adminsContract.retrieveFunctionAdmin(msg.sender, _selector) == true || adminsContract.retrieveGlobalAdmin(msg.sender) == true , "Not allowed");
_;
}
// certain functions can only be called by a collection, global or function admin
modifier CollectionAdminRequired(uint256 _collectionID, bytes4 _selector) {
require(adminsContract.retrieveCollectionAdmin(msg.sender,_collectionID) == true || adminsContract.retrieveFunctionAdmin(msg.sender, _selector) == true || adminsContract.retrieveGlobalAdmin(msg.sender) == true, "Not allowed");
_;
}
// function to add a collection's minting costs
function setCollectionCosts(uint256 _collectionID, uint256 _collectionMintCost, uint256 _collectionEndMintCost, uint256 _rate, uint256 _timePeriod, uint8 _salesOption, address _delAddress) public CollectionAdminRequired(_collectionID, this.setCollectionCosts.selector) {
require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data");
collectionPhases[_collectionID].collectionMintCost = _collectionMintCost;
collectionPhases[_collectionID].collectionEndMintCost = _collectionEndMintCost;
collectionPhases[_collectionID].rate = _rate;
collectionPhases[_collectionID].timePeriod = _timePeriod;
collectionPhases[_collectionID].salesOption = _salesOption;
collectionPhases[_collectionID].delAddress = _delAddress;
setMintingCosts[_collectionID] = true;
}
// function to add a collection's minting phases and merkleroot
function setCollectionPhases(uint256 _collectionID, uint _allowlistStartTime, uint _allowlistEndTime, uint _publicStartTime, uint _publicEndTime, bytes32 _merkleRoot) public CollectionAdminRequired(_collectionID, this.setCollectionPhases.selector) {
require(setMintingCosts[_collectionID] == true, "Set Costs");
collectionPhases[_collectionID].allowlistStartTime = _allowlistStartTime;
collectionPhases[_collectionID].allowlistEndTime = _allowlistEndTime;
collectionPhases[_collectionID].merkleRoot = _merkleRoot;
collectionPhases[_collectionID].publicStartTime = _publicStartTime;
collectionPhases[_collectionID].publicEndTime = _publicEndTime;
}
// airdrop function
function airDropTokens(address[] memory _recipients, string[] memory _tokenData, uint256[] memory _saltfun_o, uint256 _collectionID, uint256[] memory _numberOfTokens) public FunctionAdminRequired(this.airDropTokens.selector) {
require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data");
uint256 collectionTokenMintIndex;
for (uint256 y=0; y< _recipients.length; y++) {
collectionTokenMintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID) + _numberOfTokens[y] - 1;
require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_collectionID), "No supply");
for(uint256 i = 0; i < _numberOfTokens[y]; i++) {
uint256 mintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID);
gencore.airDropTokens(mintIndex, _recipients[y], _tokenData[y], _saltfun_o[y], _collectionID);
}
}
}
// mint function for allowlist or public minting
function mint(uint256 _collectionID, uint256 _numberOfTokens, uint256 _maxAllowance, string memory _tokenData, address _mintTo, bytes32[] calldata merkleProof, address _delegator, uint256 _saltfun_o) public payable {
require(setMintingCosts[_collectionID] == true && _numberOfTokens > 0, "err");
uint256 col = _collectionID;
address mintingAddress;
uint256 phase;
string memory tokData = _tokenData;
if (block.timestamp >= collectionPhases[col].allowlistStartTime && block.timestamp < collectionPhases[col].allowlistEndTime) {
phase = 1;
bytes32 node;
if (_delegator != 0x0000000000000000000000000000000000000000) {
bool isAllowedToMint;
isAllowedToMint = dmc.retrieveGlobalStatusOfDelegation(_delegator, 0x8888888888888888888888888888888888888888, msg.sender, 1) || dmc.retrieveGlobalStatusOfDelegation(_delegator, 0x8888888888888888888888888888888888888888, msg.sender, 2);
if (isAllowedToMint == false) {
isAllowedToMint = dmc.retrieveGlobalStatusOfDelegation(_delegator, collectionPhases[col].delAddress, msg.sender, 1) || dmc.retrieveGlobalStatusOfDelegation(_delegator, collectionPhases[col].delAddress, msg.sender, 2);
}
require(isAllowedToMint == true, "No delegation");
node = keccak256(bytes.concat(keccak256((abi.encodePacked(_delegator, _maxAllowance, tokData)))));
require(_maxAllowance >= gencore.retrieveTokensMintedALPerAddress(col, _delegator) + _numberOfTokens, "AL limit");
mintingAddress = _delegator;
} else {
node = keccak256(bytes.concat(keccak256((abi.encodePacked(msg.sender, _maxAllowance, tokData)))));
require(_maxAllowance >= gencore.retrieveTokensMintedALPerAddress(col, msg.sender) + _numberOfTokens, "AL limit");
mintingAddress = msg.sender;
}
require(MerkleProof.verifyCalldata(merkleProof, collectionPhases[col].merkleRoot, node), 'invalid proof');
} else if (block.timestamp >= collectionPhases[col].publicStartTime && block.timestamp <= collectionPhases[col].publicEndTime) {
phase = 2;
require(_numberOfTokens <= gencore.viewMaxAllowance(col), "Change no of tokens");
require(gencore.retrieveTokensMintedPublicPerAddress(col, msg.sender) + _numberOfTokens <= gencore.viewMaxAllowance(col), "Max");
mintingAddress = msg.sender;
tokData = '"public"';
} else {
revert("No minting");
}
uint256 collectionTokenMintIndex;
collectionTokenMintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col) + _numberOfTokens - 1;
require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(col), "No supply");
require(msg.value >= (getPrice(col) * _numberOfTokens), "Wrong ETH");
// refund excess
{
uint256 excess = calculateExcess(msg.value, getPrice(col) * _numberOfTokens);
collectionTotalAmount[col] = collectionTotalAmount[col] + msg.value - excess;
}
// check mechanism for sale option 3
if (collectionPhases[col].salesOption == 3) {
uint timeOfLastMint;
if (lastMintDate[col] == 0) {
// for only public minting set the allowliststarttime as publicstarttime
timeOfLastMint = collectionPhases[col].allowlistStartTime - collectionPhases[col].timePeriod;
} else {
timeOfLastMint = lastMintDate[col];
}
// calculate periods and check if a period has passed in order to allow minting
uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[col].timePeriod;
// users are able to mint after a period passes
// unminted tokens from previous periods are transferred for minting into new periods
// 1 mint at a time period
require(tDiff>=1 && _numberOfTokens == 1, "1 mint/period");
// exclude tokens ex. airdrop tokens so they do not affect lastMintDate
lastMintDate[col] = collectionPhases[col].allowlistStartTime + (collectionPhases[col].timePeriod * (gencore.viewCirSupply(col) - excludeTokensCounter[col]));
}
// mint tokens
for(uint256 i = 0; i < _numberOfTokens; i++) {
uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
gencore.mint(mintIndex, mintingAddress, _mintTo, tokData, _saltfun_o, col, phase);
}
}
// burn to mint function (does not require contract approval)
function burnToMint(uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o) public payable {
require(setMintingCosts[_mintCollectionID] == true && burnToMintCollections[_burnCollectionID][_mintCollectionID] == true, "init err");
require(block.timestamp >= collectionPhases[_mintCollectionID].publicStartTime && block.timestamp <= collectionPhases[_mintCollectionID].publicEndTime,"No minting");
require ((_tokenId >= gencore.viewTokensIndexMin(_burnCollectionID)) && (_tokenId <= gencore.viewTokensIndexMax(_burnCollectionID)), "col/token id error");
uint256 collectionTokenMintIndex;
collectionTokenMintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID);
require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_mintCollectionID), "No supply");
require(msg.value >= getPrice(_mintCollectionID), "Wrong ETH");
// refund excess
{
uint256 excess = calculateExcess(msg.value, getPrice(_mintCollectionID));
collectionTotalAmount[_mintCollectionID] = collectionTotalAmount[_mintCollectionID] + msg.value - excess;
}
uint256 mintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID);
// burn and mint token
address burner = msg.sender;
gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner);
}
// mint and auction
function mintAndAuction(address _recipient, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint _auctionEndTime) public FunctionAdminRequired(this.mintAndAuction.selector) {
require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data");
uint256 collectionTokenMintIndex;
collectionTokenMintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID);
require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_collectionID), "No supply");
uint256 mintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID);
uint timeOfLastMint;
// 1 token per period can be minted and send to auction
// time period can be set for any sales model
if (lastMintDate[_collectionID] == 0) {
// for public sale set the allowliststarttime the same time as publicstarttime
timeOfLastMint = collectionPhases[_collectionID].allowlistStartTime - collectionPhases[_collectionID].timePeriod;
} else {
timeOfLastMint = lastMintDate[_collectionID];
}
// calculate periods and check if a period has passed in order to allow minting
uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[_collectionID].timePeriod;
// admins are able to mint after a period passes
require(tDiff>=1, "1 mint/period");
lastMintDate[_collectionID] = collectionPhases[_collectionID].allowlistStartTime + (collectionPhases[_collectionID].timePeriod * ((gencore.viewCirSupply(_collectionID) - excludeTokensCounter[_collectionID])));
require(_auctionEndTime >= block.timestamp + 600); // 10mins min auction
mintToAuctionData[mintIndex] = _auctionEndTime;
mintToAuctionStatus[mintIndex] = true;
// token is airdropped to the _recipient address
gencore.airDropTokens(mintIndex, _recipient, _tokenData, _saltfun_o, _collectionID);
}
// function to exclude a specific no of tokens during sales model 3 or reset lastMintDate
function excludeTokensOrResetLD(uint256 _option, uint256 _collectionID, uint256 _excludeCounter) public FunctionAdminRequired(this.excludeTokensOrResetLD.selector) {
if (_option == 1) {
excludeTokensCounter[_collectionID] = _excludeCounter;
} else {
lastMintDate[_collectionID] = 0;
}
}
// function to refund any excess amount
function calculateExcess(uint256 _value, uint256 _price) internal returns(uint256) {
uint256 excess;
excess = _value - _price;
(bool success1, ) = payable(msg.sender).call{value: excess}("");
require(success1, "ETH failed");
return(excess);
}
// function to initialize burn to mint for NextGen collections
function initializeBurn(uint256 _burnCollectionID, uint256 _mintCollectionID, bool _status) public FunctionAdminRequired(this.initializeBurn.selector) {
require((gencore.retrievewereDataAdded(_burnCollectionID) == true) && (gencore.retrievewereDataAdded(_mintCollectionID) == true), "No data");
burnToMintCollections[_burnCollectionID][_mintCollectionID] = _status;
}
// function to initialize external burn or swap to mint
function initializeExternalBurnOrSwap(address _erc721Collection, uint256 _burnCollectionID, uint256 _mintCollectionID, uint256 _tokmin, uint256 _tokmax, address _burnOrSwapAddress, bool _status) public FunctionAdminRequired(this.initializeExternalBurnOrSwap.selector) {
bytes32 externalCol = keccak256(abi.encodePacked(_erc721Collection,_burnCollectionID));
require((gencore.retrievewereDataAdded(_mintCollectionID) == true), "No data");
burnExternalToMintCollections[externalCol][_mintCollectionID] = _status;
burnOrSwapAddress[externalCol] = _burnOrSwapAddress;
burnOrSwapIds[externalCol][0] = _tokmin;
burnOrSwapIds[externalCol][1] = _tokmax;
}
// burn or swap to mint (requires contract approval)
function burnOrSwapExternalToMint(address _erc721Collection, uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, string memory _tokenData, bytes32[] calldata merkleProof, uint256 _saltfun_o) public payable {
bytes32 externalCol = keccak256(abi.encodePacked(_erc721Collection,_burnCollectionID));
require(setMintingCosts[_mintCollectionID] == true && burnExternalToMintCollections[externalCol][_mintCollectionID] == true, "init err");
address ownerOfToken = IERC721(_erc721Collection).ownerOf(_tokenId);
if (msg.sender != ownerOfToken) {
bool isAllowedToMint;
isAllowedToMint = dmc.retrieveGlobalStatusOfDelegation(ownerOfToken, 0x8888888888888888888888888888888888888888, msg.sender, 1) || dmc.retrieveGlobalStatusOfDelegation(ownerOfToken, 0x8888888888888888888888888888888888888888, msg.sender, 2);
if (isAllowedToMint == false) {
isAllowedToMint = dmc.retrieveGlobalStatusOfDelegation(ownerOfToken, _erc721Collection, msg.sender, 1) || dmc.retrieveGlobalStatusOfDelegation(ownerOfToken, _erc721Collection, msg.sender, 2);
}
require(isAllowedToMint == true, "No delegation");
}
require(_tokenId >= burnOrSwapIds[externalCol][0] && _tokenId <= burnOrSwapIds[externalCol][1], "Token id does not match");
IERC721(_erc721Collection).safeTransferFrom(ownerOfToken, burnOrSwapAddress[externalCol], _tokenId);
uint256 col = _mintCollectionID;
address mintingAddress;
uint256 phase;
string memory tokData = _tokenData;
if (block.timestamp >= collectionPhases[col].allowlistStartTime && block.timestamp < collectionPhases[col].allowlistEndTime) {
phase = 1;
bytes32 node;
node = keccak256(bytes.concat(keccak256((abi.encodePacked(_tokenId, tokData)))));
mintingAddress = ownerOfToken;
require(MerkleProof.verifyCalldata(merkleProof, collectionPhases[col].merkleRoot, node), 'invalid proof');
} else if (block.timestamp >= collectionPhases[col].publicStartTime && block.timestamp <= collectionPhases[col].publicEndTime) {
phase = 2;
mintingAddress = ownerOfToken;
tokData = '"public"';
} else {
revert("No minting");
}
uint256 collectionTokenMintIndex;
collectionTokenMintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(col), "No supply");
require(msg.value >= getPrice(col), "Wrong ETH");
// refund excess
{
uint256 excess = calculateExcess(msg.value, getPrice(col));
collectionTotalAmount[col] = collectionTotalAmount[col] + msg.value - excess;
}
uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col);
gencore.mint(mintIndex, mintingAddress, ownerOfToken, tokData, _saltfun_o, col, phase);
}
// function to set primary splits
function setPrimaryAndSecondarySplits(uint256 _collectionID, uint256 _artistPrSplit, uint256 _teamPrSplit, uint256 _artistSecSplit, uint256 _teamSecSplit) public FunctionAdminRequired(this.setPrimaryAndSecondarySplits.selector) {
require(_artistPrSplit + _teamPrSplit == 100, "splits need to be 100%");
require(_artistSecSplit + _teamSecSplit == 100, "splits need to be 100%");
collectionRoyaltiesPrimarySplits[_collectionID].artistPercentage = _artistPrSplit;
collectionRoyaltiesPrimarySplits[_collectionID].teamPercentage = _teamPrSplit;
collectionRoyaltiesSecondarySplits[_collectionID].artistPercentage = _artistSecSplit;
collectionRoyaltiesSecondarySplits[_collectionID].teamPercentage = _teamSecSplit;
}
// function to propose primary addresses and percentages for each address
function proposePrimaryAddressesAndPercentages(uint256 _collectionID, address _primaryAdd1, address _primaryAdd2, address _primaryAdd3, uint256 _add1Percentage, uint256 _add2Percentage, uint256 _add3Percentage) public ArtistOrAdminRequired(_collectionID, this.proposePrimaryAddressesAndPercentages.selector) {
require (collectionArtistPrimaryAddresses[_collectionID].approvedStatus == false, "Already approved");
require (_add1Percentage + _add2Percentage + _add3Percentage == collectionRoyaltiesPrimarySplits[_collectionID].artistPercentage, "Check %");
collectionArtistPrimaryAddresses[_collectionID].primaryAdd1 = _primaryAdd1;
collectionArtistPrimaryAddresses[_collectionID].primaryAdd2 = _primaryAdd2;
collectionArtistPrimaryAddresses[_collectionID].primaryAdd3 = _primaryAdd3;
collectionArtistPrimaryAddresses[_collectionID].add1Percentage = _add1Percentage;
collectionArtistPrimaryAddresses[_collectionID].add2Percentage = _add2Percentage;
collectionArtistPrimaryAddresses[_collectionID].add3Percentage = _add3Percentage;
collectionArtistPrimaryAddresses[_collectionID].setStatus = true;
collectionArtistPrimaryAddresses[_collectionID].approvedStatus = false;
}
// function to propose secondary addresses and percentages for each address
function proposeSecondaryAddressesAndPercentages(uint256 _collectionID, address _secondaryAdd1, address _secondaryAdd2, address _secondaryAdd3, uint256 _add1Percentage, uint256 _add2Percentage, uint256 _add3Percentage) public ArtistOrAdminRequired(_collectionID, this.proposeSecondaryAddressesAndPercentages.selector) {
require (collectionArtistSecondaryAddresses[_collectionID].approvedStatus == false, "Already approved");
require (_add1Percentage + _add2Percentage + _add3Percentage == collectionRoyaltiesSecondarySplits[_collectionID].artistPercentage, "Check %");
collectionArtistSecondaryAddresses[_collectionID].secondaryAdd1 = _secondaryAdd1;
collectionArtistSecondaryAddresses[_collectionID].secondaryAdd2 = _secondaryAdd2;
collectionArtistSecondaryAddresses[_collectionID].secondaryAdd3 = _secondaryAdd3;
collectionArtistSecondaryAddresses[_collectionID].add1Percentage = _add1Percentage;
collectionArtistSecondaryAddresses[_collectionID].add2Percentage = _add2Percentage;
collectionArtistSecondaryAddresses[_collectionID].add3Percentage = _add3Percentage;
collectionArtistSecondaryAddresses[_collectionID].setStatus = true;
collectionArtistSecondaryAddresses[_collectionID].approvedStatus = false;
}
// function to accept primary addresses and percentages
function acceptAddressesAndPercentages(uint256 _collectionID, bool _statusPrimary, bool _statusSecondary) public FunctionAdminRequired(this.acceptAddressesAndPercentages.selector) {
require(collectionArtistPrimaryAddresses[_collectionID].setStatus == true && collectionArtistSecondaryAddresses[_collectionID].setStatus == true, "Propose Addresses");
collectionArtistPrimaryAddresses[_collectionID].approvedStatus = _statusPrimary;
collectionArtistSecondaryAddresses[_collectionID].approvedStatus = _statusSecondary;
if (_statusPrimary == false) {
collectionArtistPrimaryAddresses[_collectionID].setStatus = false;
} else if (_statusSecondary == false) {
collectionArtistSecondaryAddresses[_collectionID].setStatus = false;
}
}
// function to transfer funds to the artist and team
function payArtist(uint256 _collectionID, address _team1, address _team2, uint256 _teamperc1, uint256 _teamperc2) public FunctionAdminRequired(this.payArtist.selector) {
require(collectionArtistPrimaryAddresses[_collectionID].approvedStatus == true, "Accept Royalties");
require(collectionTotalAmount[_collectionID] > 0, "Collection Balance must be grater than 0");
require(collectionRoyaltiesPrimarySplits[_collectionID].artistPercentage + _teamperc1 + _teamperc2 == 100, "Change percentages");
uint256 royalties = collectionTotalAmount[_collectionID];
collectionTotalAmount[_collectionID] = 0;
address tm1 = _team1;
address tm2 = _team2;
uint256 colId = _collectionID;
uint256 artistRoyalties1;
uint256 artistRoyalties2;
uint256 artistRoyalties3;
uint256 teamRoyalties1;
uint256 teamRoyalties2;
artistRoyalties1 = royalties * collectionArtistPrimaryAddresses[colId].add1Percentage / 100;
artistRoyalties2 = royalties * collectionArtistPrimaryAddresses[colId].add2Percentage / 100;
artistRoyalties3 = royalties * collectionArtistPrimaryAddresses[colId].add3Percentage / 100;
teamRoyalties1 = royalties * _teamperc1 / 100;
teamRoyalties2 = royalties * _teamperc2 / 100;
(bool success1, ) = payable(collectionArtistPrimaryAddresses[colId].primaryAdd1).call{value: artistRoyalties1}("");
(bool success2, ) = payable(collectionArtistPrimaryAddresses[colId].primaryAdd2).call{value: artistRoyalties2}("");
(bool success3, ) = payable(collectionArtistPrimaryAddresses[colId].primaryAdd3).call{value: artistRoyalties3}("");
(bool success4, ) = payable(tm1).call{value: teamRoyalties1}("");
(bool success5, ) = payable(tm2).call{value: teamRoyalties2}("");
require(success1, "ETH failed");
require(success2, "ETH failed");
require(success3, "ETH failed");
require(success4, "ETH failed");
require(success5, "ETH failed");
}
// function to update core contract
function updateCoreContract(address _gencore) public FunctionAdminRequired(this.updateCoreContract.selector) {
gencore = INextGenCore(_gencore);
}
// function to update admin contract
function updateAdminContract(address _newadminsContract) public FunctionAdminRequired(this.updateAdminContract.selector) {
require(INextGenAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin");
adminsContract = INextGenAdmins(_newadminsContract);
}
// function to withdraw any balance from the smart contract
function emergencyWithdraw() public FunctionAdminRequired(this.emergencyWithdraw.selector) {
uint balance = address(this).balance;
address admin = adminsContract.owner();
(bool success, ) = payable(admin).call{value: balance}("");
require(success, "ETH failed");
emit Withdraw(msg.sender, success, balance);
}
// function to retrieve primary splits between artist and team
function retrievePrimarySplits(uint256 _collectionID) public view returns(uint256, uint256){
return (collectionRoyaltiesPrimarySplits[_collectionID].artistPercentage, collectionRoyaltiesPrimarySplits[_collectionID].teamPercentage);
}
// function to retrieve primary addresses and percentages
function retrievePrimaryAddressesAndPercentages(uint256 _collectionID) public view returns(address, address, address, uint256, uint256, uint256, bool){
return (collectionArtistPrimaryAddresses[_collectionID].primaryAdd1, collectionArtistPrimaryAddresses[_collectionID].primaryAdd2, collectionArtistPrimaryAddresses[_collectionID].primaryAdd3, collectionArtistPrimaryAddresses[_collectionID].add1Percentage, collectionArtistPrimaryAddresses[_collectionID].add2Percentage, collectionArtistPrimaryAddresses[_collectionID].add3Percentage, collectionArtistPrimaryAddresses[_collectionID].approvedStatus);
}
// function to retrieve secondary splits between artist and team
function retrieveSecondarySplits(uint256 _collectionID) public view returns(uint256, uint256){
return (collectionRoyaltiesSecondarySplits[_collectionID].artistPercentage, collectionRoyaltiesSecondarySplits[_collectionID].teamPercentage);
}
// function to retrieve secondary addresses and percentages
function retrieveSecondaryAddressesAndPercentages(uint256 _collectionID) public view returns(address, address, address, uint256, uint256, uint256, bool){
return (collectionArtistSecondaryAddresses[_collectionID].secondaryAdd1, collectionArtistSecondaryAddresses[_collectionID].secondaryAdd2, collectionArtistSecondaryAddresses[_collectionID].secondaryAdd3, collectionArtistSecondaryAddresses[_collectionID].add1Percentage, collectionArtistSecondaryAddresses[_collectionID].add2Percentage, collectionArtistSecondaryAddresses[_collectionID].add3Percentage, collectionArtistSecondaryAddresses[_collectionID].approvedStatus);
}
// function to retrieve the phases and merkle root of a collection
function retrieveCollectionPhases(uint256 _collectionID) public view returns(uint, uint, bytes32, uint, uint){
return (collectionPhases[_collectionID].allowlistStartTime, collectionPhases[_collectionID].allowlistEndTime, collectionPhases[_collectionID].merkleRoot, collectionPhases[_collectionID].publicStartTime, collectionPhases[_collectionID].publicEndTime);
}
// function to retrieve the minting details of a collection
function retrieveCollectionMintingDetails(uint256 _collectionID) public view returns(uint256, uint256, uint256, uint256, uint8, address){
return (collectionPhases[_collectionID].collectionMintCost, collectionPhases[_collectionID].collectionEndMintCost, collectionPhases[_collectionID].rate, collectionPhases[_collectionID].timePeriod, collectionPhases[_collectionID].salesOption, collectionPhases[_collectionID].delAddress);
}
// retrieve minter contract status
function isMinterContract() external view returns (bool) {
return true;
}
// retrieve minting end time
function getEndTime(uint256 _collectionID) external view returns (uint) {
return collectionPhases[_collectionID].publicEndTime;
}
// retrieve auction end time
function getAuctionEndTime(uint256 _tokenId) external view returns (uint) {
return mintToAuctionData[_tokenId];
}
// retrieve auction status
function getAuctionStatus(uint256 _tokenId) external view returns (bool) {
return mintToAuctionStatus[_tokenId];
}
// retrieve the minting price of collection
function getPrice(uint256 _collectionId) public view returns (uint256) {
uint tDiff;
if (collectionPhases[_collectionId].salesOption == 3) {
// periodic sale model
// if rate > 0 minting price increases by rate (percentage) during each mint
if (collectionPhases[_collectionId].rate > 0) {
return collectionPhases[_collectionId].collectionMintCost + ((collectionPhases[_collectionId].collectionMintCost * collectionPhases[_collectionId].rate / 100) * (gencore.viewCirSupply(_collectionId) - excludeTokensCounter[_collectionId]));
} else {
return collectionPhases[_collectionId].collectionMintCost;
}
} else if (collectionPhases[_collectionId].salesOption == 2 && block.timestamp >= collectionPhases[_collectionId].allowlistStartTime && block.timestamp <= collectionPhases[_collectionId].publicEndTime){
// decreases during a time period
// if only public minting set allowlistStartTime = publicStartTime
// if rate = 0 exponential descending model, otherwise, linear descending model
// if rate is set the linear decrase each period per rate
tDiff = (block.timestamp - collectionPhases[_collectionId].allowlistStartTime) / collectionPhases[_collectionId].timePeriod;
uint256 price;
uint256 decreaserate;
if (collectionPhases[_collectionId].rate == 0) {
price = collectionPhases[_collectionId].collectionMintCost / (tDiff + 1);
decreaserate = ((price - (collectionPhases[_collectionId].collectionMintCost / (tDiff + 2))) / collectionPhases[_collectionId].timePeriod) * ((block.timestamp - (tDiff * collectionPhases[_collectionId].timePeriod) - collectionPhases[_collectionId].allowlistStartTime));
} else {
if (((collectionPhases[_collectionId].collectionMintCost - collectionPhases[_collectionId].collectionEndMintCost) / (collectionPhases[_collectionId].rate)) >= tDiff) {
price = collectionPhases[_collectionId].collectionMintCost - (tDiff * collectionPhases[_collectionId].rate);
} else {
price = collectionPhases[_collectionId].collectionEndMintCost;
}
}
if (price - decreaserate > collectionPhases[_collectionId].collectionEndMintCost) {
return price - decreaserate;
} else {
return collectionPhases[_collectionId].collectionEndMintCost;
}
} else {
// fixed price model
return collectionPhases[_collectionId].collectionMintCost;
}
}
}
{
"compilationTarget": {
"MinterContract.sol": "NextGenMinterContract"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_gencore","type":"address"},{"internalType":"address","name":"_del","type":"address"},{"internalType":"address","name":"_adminsContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_add","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"},{"indexed":true,"internalType":"uint256","name":"funds","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"bool","name":"_statusPrimary","type":"bool"},{"internalType":"bool","name":"_statusSecondary","type":"bool"}],"name":"acceptAddressesAndPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"string[]","name":"_tokenData","type":"string[]"},{"internalType":"uint256[]","name":"_saltfun_o","type":"uint256[]"},{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256[]","name":"_numberOfTokens","type":"uint256[]"}],"name":"airDropTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"burnExternalToMintCollections","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"burnOrSwapAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_erc721Collection","type":"address"},{"internalType":"uint256","name":"_burnCollectionID","type":"uint256"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_mintCollectionID","type":"uint256"},{"internalType":"string","name":"_tokenData","type":"string"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_saltfun_o","type":"uint256"}],"name":"burnOrSwapExternalToMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnCollectionID","type":"uint256"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_mintCollectionID","type":"uint256"},{"internalType":"uint256","name":"_saltfun_o","type":"uint256"}],"name":"burnToMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"burnToMintCollections","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collectionTotalAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dmc","outputs":[{"internalType":"contract IDelegationManagementContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"excludeTokensCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_option","type":"uint256"},{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_excludeCounter","type":"uint256"}],"name":"excludeTokensOrResetLD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gencore","outputs":[{"internalType":"contract INextGenCore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAuctionEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAuctionStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"getEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionId","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnCollectionID","type":"uint256"},{"internalType":"uint256","name":"_mintCollectionID","type":"uint256"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"initializeBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_erc721Collection","type":"address"},{"internalType":"uint256","name":"_burnCollectionID","type":"uint256"},{"internalType":"uint256","name":"_mintCollectionID","type":"uint256"},{"internalType":"uint256","name":"_tokmin","type":"uint256"},{"internalType":"uint256","name":"_tokmax","type":"uint256"},{"internalType":"address","name":"_burnOrSwapAddress","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"initializeExternalBurnOrSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMinterContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastMintDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_numberOfTokens","type":"uint256"},{"internalType":"uint256","name":"_maxAllowance","type":"uint256"},{"internalType":"string","name":"_tokenData","type":"string"},{"internalType":"address","name":"_mintTo","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"address","name":"_delegator","type":"address"},{"internalType":"uint256","name":"_saltfun_o","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"string","name":"_tokenData","type":"string"},{"internalType":"uint256","name":"_saltfun_o","type":"uint256"},{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_auctionEndTime","type":"uint256"}],"name":"mintAndAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"address","name":"_team1","type":"address"},{"internalType":"address","name":"_team2","type":"address"},{"internalType":"uint256","name":"_teamperc1","type":"uint256"},{"internalType":"uint256","name":"_teamperc2","type":"uint256"}],"name":"payArtist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"address","name":"_primaryAdd1","type":"address"},{"internalType":"address","name":"_primaryAdd2","type":"address"},{"internalType":"address","name":"_primaryAdd3","type":"address"},{"internalType":"uint256","name":"_add1Percentage","type":"uint256"},{"internalType":"uint256","name":"_add2Percentage","type":"uint256"},{"internalType":"uint256","name":"_add3Percentage","type":"uint256"}],"name":"proposePrimaryAddressesAndPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"address","name":"_secondaryAdd1","type":"address"},{"internalType":"address","name":"_secondaryAdd2","type":"address"},{"internalType":"address","name":"_secondaryAdd3","type":"address"},{"internalType":"uint256","name":"_add1Percentage","type":"uint256"},{"internalType":"uint256","name":"_add2Percentage","type":"uint256"},{"internalType":"uint256","name":"_add3Percentage","type":"uint256"}],"name":"proposeSecondaryAddressesAndPercentages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrieveCollectionMintingDetails","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrieveCollectionPhases","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrievePrimaryAddressesAndPercentages","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrievePrimarySplits","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrieveSecondaryAddressesAndPercentages","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"}],"name":"retrieveSecondarySplits","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_collectionMintCost","type":"uint256"},{"internalType":"uint256","name":"_collectionEndMintCost","type":"uint256"},{"internalType":"uint256","name":"_rate","type":"uint256"},{"internalType":"uint256","name":"_timePeriod","type":"uint256"},{"internalType":"uint8","name":"_salesOption","type":"uint8"},{"internalType":"address","name":"_delAddress","type":"address"}],"name":"setCollectionCosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_allowlistStartTime","type":"uint256"},{"internalType":"uint256","name":"_allowlistEndTime","type":"uint256"},{"internalType":"uint256","name":"_publicStartTime","type":"uint256"},{"internalType":"uint256","name":"_publicEndTime","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setCollectionPhases","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collectionID","type":"uint256"},{"internalType":"uint256","name":"_artistPrSplit","type":"uint256"},{"internalType":"uint256","name":"_teamPrSplit","type":"uint256"},{"internalType":"uint256","name":"_artistSecSplit","type":"uint256"},{"internalType":"uint256","name":"_teamSecSplit","type":"uint256"}],"name":"setPrimaryAndSecondarySplits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newadminsContract","type":"address"}],"name":"updateAdminContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gencore","type":"address"}],"name":"updateCoreContract","outputs":[],"stateMutability":"nonpayable","type":"function"}]