// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)pragmasolidity ^0.8.1;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0// for contracts in construction, since the code is only stored at the end// of the constructor execution.return account.code.length>0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target, bytesmemory data, uint256 value) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
(bool success, bytesmemory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/functionverifyCallResultFromTarget(address target,
bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
if (success) {
if (returndata.length==0) {
// only check isContract if the call was successful and the return data is empty// otherwise we already know that it was a contractrequire(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function_revert(bytesmemory returndata, stringmemory errorMessage) privatepure{
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly/// @solidity memory-safe-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Contract Source Code
File 2 of 22: Base64.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)pragmasolidity ^0.8.19;/**
* @dev Provides a set of functions to operate with Base64 strings.
*
* _Available since v4.5._
*/libraryBase64{
/**
* @dev Base64 Encoding/Decoding Table
*/stringinternalconstant _TABLE ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/functionencode(bytesmemory data) internalpurereturns (stringmemory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/if (data.length==0) return"";
// Loads the table into memorystringmemory table = _TABLE;
// Encoding takes 3 bytes chunks of binary data from `bytes` data parameter// and split into 4 numbers of 6 bits.// The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up// - `data.length + 2` -> Round up// - `/ 3` -> Number of 3-bytes chunks// - `4 *` -> 4 characters for each chunkstringmemory result =newstring(4* ((data.length+2) /3));
/// @solidity memory-safe-assemblyassembly {
// Prepare the lookup table (skip the first "length" byte)let tablePtr :=add(table, 1)
// Prepare result pointer, jump over lengthlet resultPtr :=add(result, 32)
// Run over the input, 3 bytes at a timefor {
let dataPtr := data
let endPtr :=add(data, mload(data))
} lt(dataPtr, endPtr) {
} {
// Advance 3 bytes
dataPtr :=add(dataPtr, 3)
let input :=mload(dataPtr)
// To write each character, shift the 3 bytes (18 bits) chunk// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)// and apply logical AND with 0x3F which is the number of// the previous character in the ASCII table prior to the Base64 Table// The result is then added to the table to get the character to write,// and finally write it in the result pointer but with a left shift// of 256 (1 byte) - 8 (1 ASCII char) = 248 bitsmstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr :=add(resultPtr, 1) // Advancemstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr :=add(resultPtr, 1) // Advancemstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr :=add(resultPtr, 1) // Advancemstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr :=add(resultPtr, 1) // Advance
}
// When data `bytes` is not exactly 3 bytes long// it is padded with `=` characters at the endswitchmod(mload(data), 3)
case1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
return result;
}
}
Contract Source Code
File 3 of 22: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 4 of 22: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)pragmasolidity ^0.8.0;/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/import"./IERC165.sol";
abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 5 of 22: ERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)pragmasolidity ^0.8.19;import"./IERC2981.sol";
import"./ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/abstractcontractERC2981isIERC2981, ERC165{
structRoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/errorERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/errorERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/errorERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/errorERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC165) returns (bool) {
return interfaceId ==type(IERC2981).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/functionroyaltyInfo(uint256 tokenId, uint256 salePrice) publicviewvirtualreturns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver ==address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/function_feeDenominator() internalpurevirtualreturns (uint96) {
return10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setDefaultRoyalty(address receiver, uint96 feeNumerator) internalvirtual{
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale pricerevert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver ==address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/function_deleteDefaultRoyalty() internalvirtual{
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internalvirtual{
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale pricerevert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver ==address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/function_resetTokenRoyalty(uint256 tokenId) internalvirtual{
delete _tokenRoyaltyInfo[tokenId];
}
}
Contract Source Code
File 6 of 22: ERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)pragmasolidity ^0.8.0;/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/import"./Context.sol";
import"./ERC165.sol";
import"./IERC721.sol";
import"./IERC721Metadata.sol";
import"./Address.sol";
import"./Strings.sol";
import"./IERC721Receiver.sol";
contractERC721isContext, ERC165, IERC721, IERC721Metadata{
usingAddressforaddress;
usingStringsforuint256;
// Token namestringprivate _name;
// Token symbolstringprivate _symbol;
// Mapping from token ID to owner addressmapping(uint256=>address) private _owners;
// Mapping owner address to token countmapping(address=>uint256) private _balances;
// Mapping from token ID to approved addressmapping(uint256=>address) private _tokenApprovals;
// Mapping from owner to operator approvalsmapping(address=>mapping(address=>bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165, IERC165) returns (bool) {
return
interfaceId ==type(IERC721).interfaceId||
interfaceId ==type(IERC721Metadata).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/functionbalanceOf(address owner) publicviewvirtualoverridereturns (uint256) {
require(owner !=address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/functionownerOf(uint256 tokenId) publicviewvirtualoverridereturns (address) {
address owner = _ownerOf(tokenId);
require(owner !=address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewvirtualoverridereturns (stringmemory) {
_requireMinted(tokenId);
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length>0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return"";
}
/**
* @dev See {IERC721-approve}.
*/functionapprove(address to, uint256 tokenId) publicvirtualoverride{
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/functiongetApproved(uint256 tokenId) publicviewvirtualoverridereturns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtualoverride{
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualoverridereturns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/functiontransferFrom(addressfrom, address to, uint256 tokenId) publicvirtualoverride{
//solhint-disable-next-line max-line-lengthrequire(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId) publicvirtualoverride{
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytesmemory data) publicvirtualoverride{
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @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.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeTransfer(addressfrom, address to, uint256 tokenId, bytesmemory data) internalvirtual{
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/function_ownerOf(uint256 tokenId) internalviewvirtualreturns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/function_exists(uint256 tokenId) internalviewvirtualreturns (bool) {
return _ownerOf(tokenId) !=address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/function_isApprovedOrOwner(address spender, uint256 tokenId) internalviewvirtualreturns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeMint(address to, uint256 tokenId) internalvirtual{
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeMint(address to, uint256 tokenId, bytesmemory data) internalvirtual{
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/function_mint(address to, uint256 tokenId) internalvirtual{
require(to !=address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hookrequire(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.// Given that tokens are minted one by one, it is impossible in practice that// this ever happens. Might change if we allow batch minting.// The ERC fails to describe this case.
_balances[to] +=1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/function_burn(uint256 tokenId) internalvirtual{
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvalsdelete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred// out than the owner initially received through minting and transferring in.
_balances[owner] -=1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/function_transfer(addressfrom, address to, uint256 tokenId) internalvirtual{
require(ERC721.ownerOf(tokenId) ==from, "ERC721: transfer from incorrect owner");
require(to !=address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hookrequire(ERC721.ownerOf(tokenId) ==from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous ownerdelete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:// `from`'s balance is the number of token held, which is at least one before the current// transfer.// `_balances[to]` could overflow in the conditions described in `_mint`. That would require// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -=1;
_balances[to] +=1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/function_approve(address to, uint256 tokenId) internalvirtual{
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/function_setApprovalForAll(address owner, address operator, bool approved) internalvirtual{
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/function_requireMinted(uint256 tokenId) internalviewvirtual{
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/function_checkOnERC721Received(addressfrom,
address to,
uint256 tokenId,
bytesmemory data
) privatereturns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytesmemory reason) {
if (reason.length==0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assemblyassembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
returntrue;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_beforeTokenTransfer(addressfrom, address to, uint256 firstTokenId, uint256 batchSize) internalvirtual{}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_afterTokenTransfer(addressfrom, address to, uint256 firstTokenId, uint256 batchSize) internalvirtual{}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/// solhint-disable-next-line func-name-mixedcasefunction__unsafe_increaseBalance(address account, uint256 amount) internal{
_balances[account] += amount;
}
}
Contract Source Code
File 7 of 22: ERC721Enumerable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)pragmasolidity ^0.8.0;/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/import"./ERC721.sol";
import"./IERC721Enumerable.sol";
abstractcontractERC721EnumerableisERC721, IERC721Enumerable{
// Mapping from owner to list of owned token IDsmapping(address=>mapping(uint256=>uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens listmapping(uint256=>uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumerationuint256[] private _allTokens;
// Mapping from token id to position in the allTokens arraymapping(uint256=>uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC721) returns (bool) {
return interfaceId ==type(IERC721Enumerable).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) publicviewvirtualoverridereturns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/functiontotalSupply() publicviewvirtualoverridereturns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/functiontokenByIndex(uint256 index) publicviewvirtualoverridereturns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev See {ERC721-_beforeTokenTransfer}.
*/function_beforeTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize
) internalvirtualoverride{
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
if (batchSize >1) {
// Will only trigger during construction. Batch transferring (minting) is not available afterwards.revert("ERC721Enumerable: consecutive transfers not supported");
}
uint256 tokenId = firstTokenId;
if (from==address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} elseif (from!= to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to ==address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} elseif (to !=from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/function_addTokenToOwnerEnumeration(address to, uint256 tokenId) private{
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/function_addTokenToAllTokensEnumeration(uint256 tokenId) private{
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/function_removeTokenFromOwnerEnumeration(addressfrom, uint256 tokenId) private{
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = ERC721.balanceOf(from) -1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessaryif (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the arraydelete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/function_removeTokenFromAllTokensEnumeration(uint256 tokenId) private{
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = _allTokens.length-1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding// an 'if' statement (like in _removeTokenFromOwnerEnumeration)uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index// This also deletes the contents at the last position of the arraydelete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^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}.
*/interfaceIERC165{
/**
* @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.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 10 of 22: IERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)pragmasolidity ^0.8.19;import"./IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*/interfaceIERC2981isIERC165{
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/functionroyaltyInfo(uint256 tokenId,
uint256 salePrice
) externalviewreturns (address receiver, uint256 royaltyAmount);
}
Contract Source Code
File 11 of 22: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)pragmasolidity ^0.8.0;/**
* @dev Required interface of an ERC721 compliant contract.
*/import"./IERC165.sol";
interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (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.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytescalldata 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.
*/functionsafeTransferFrom(addressfrom, 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.
*/functiontransferFrom(addressfrom, 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.
*/functionapprove(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.
*/functionsetApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
}
Contract Source Code
File 12 of 22: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)pragmasolidity ^0.8.0;/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/import"./IERC721.sol";
interfaceIERC721EnumerableisIERC721{
/**
* @dev Returns the total amount of tokens stored by the contract.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) externalviewreturns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/functiontokenByIndex(uint256 index) externalviewreturns (uint256);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)pragmasolidity ^0.8.0;/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
Contract Source Code
File 15 of 22: IMinterContract.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.19;interfaceIMinterContract{
// retrieve if the contract is minter contractfunctionisMinterContract() externalviewreturns (bool);
// retrieve the public end time of a salefunctiongetEndTime(uint256 _collectionID) externalviewreturns (uint);
// retrieve auction end timefunctiongetAuctionEndTime(uint256 _tokenId) externalviewreturns (uint);
// retrieve auction statusfunctiongetAuctionStatus(uint256 _tokenId) externalviewreturns (bool);
// retrieve primary addressesfunctionretrievePrimaryAddressesAndPercentages(uint256 _collectionID) externalviewreturns(address, address, address, uint256, uint256, uint256, bool);
// retrieve secondary addressesfunctionretrieveSecondaryAddressesAndPercentages(uint256 _collectionID) externalviewreturns(address, address, address, uint256, uint256, uint256, bool);
}
Contract Source Code
File 16 of 22: INextGenAdmins.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.19;interfaceINextGenAdmins{
// retrieve global adminfunctionretrieveGlobalAdmin(address _address) externalviewreturns(bool);
// retrieve function adminfunctionretrieveFunctionAdmin(address _address, bytes4 _selector) externalviewreturns(bool);
// retrieve collection adminfunctionretrieveCollectionAdmin(address _address, uint256 _collectionID) externalviewreturns(bool);
// retrieve if the contract is admin contractfunctionisAdminContract() externalviewreturns (bool);
// retrieve ownerfunctionowner() externalviewreturns (address);
}
Contract Source Code
File 17 of 22: IRandomizer.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.19;interfaceIRandomizer{
// function that calculates the random hash and returns it to the gencore contractfunctioncalculateTokenHash(uint256 _collectionID, uint256 _mintIndex, uint256 _saltfun_o) external;
// get randomizer contract statusfunctionisRandomizerContract() externalviewreturns (bool);
}
Contract Source Code
File 18 of 22: Math.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)pragmasolidity ^0.8.0;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
enumRounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.return a ==0 ? 0 : (a -1) / b +1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.// The surrounding unchecked block does not change this fact.// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.// See https://cs.stackexchange.com/q/138556/92363.// Does not overflow because the denominator cannot be zero at this stage in the function.uint256 twos = denominator & (~denominator +1);
assembly {
// Divide denominator by twos.
denominator :=div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 :=div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos :=add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works// in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internalpurereturns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up &&mulmod(x, y, denominator) >0) {
result +=1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/functionsqrt(uint256 a) internalpurereturns (uint256) {
if (a ==0) {
return0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.//// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.//// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`//// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.uint256 result =1<< (log2(a) >>1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision// into the expected uint128 result.unchecked {
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/functionsqrt(uint256 a, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=128;
}
if (value >>64>0) {
value >>=64;
result +=64;
}
if (value >>32>0) {
value >>=32;
result +=32;
}
if (value >>16>0) {
value >>=16;
result +=16;
}
if (value >>8>0) {
value >>=8;
result +=8;
}
if (value >>4>0) {
value >>=4;
result +=4;
}
if (value >>2>0) {
value >>=2;
result +=2;
}
if (value >>1>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result =log2(value);
return result + (rounding == Rounding.Up &&1<< result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >=10**64) {
value /=10**64;
result +=64;
}
if (value >=10**32) {
value /=10**32;
result +=32;
}
if (value >=10**16) {
value /=10**16;
result +=16;
}
if (value >=10**8) {
value /=10**8;
result +=8;
}
if (value >=10**4) {
value /=10**4;
result +=4;
}
if (value >=10**2) {
value /=10**2;
result +=2;
}
if (value >=10**1) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up &&10** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/functionlog256(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=16;
}
if (value >>64>0) {
value >>=64;
result +=8;
}
if (value >>32>0) {
value >>=32;
result +=4;
}
if (value >>16>0) {
value >>=16;
result +=2;
}
if (value >>8>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog256(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up &&1<< (result <<3) < value ? 1 : 0);
}
}
}
Contract Source Code
File 19 of 22: NextGenCore.sol
// SPDX-License-Identifier: MIT/**
*
* @title: NextGen 6529 - Core Contract
* @date: 29-January-2023
* @version: 10.31
* @author: 6529 team
*/pragmasolidity ^0.8.19;import"./ERC721Enumerable.sol";
import"./Strings.sol";
import"./Base64.sol";
import"./IRandomizer.sol";
import"./INextGenAdmins.sol";
import"./IMinterContract.sol";
import"./ERC2981.sol";
import"./Ownable.sol";
import"./IDependencyRegistry.sol";
contractNextGenCoreisERC721Enumerable, ERC2981, Ownable{
usingStringsforuint256;
// declare variablesuint256public newCollectionIndex;
// struct that holds a collection's infostructcollectionInfoStructure {
string collectionName;
string collectionArtist;
string collectionDescription;
string collectionWebsite;
string collectionLicense;
string collectionBaseURI;
string collectionLibrary;
bytes32 collectionDependencyScript;
string[] collectionScript;
}
// mapping of collectionInfo structmapping (uint256=> collectionInfoStructure) private collectionInfo;
// struct that holds a collection's additional datastructcollectionAdditonalDataStructure {
address collectionArtistAddress;
uint256 maxCollectionPurchases;
uint256 collectionCirculationSupply;
uint256 collectionTotalSupply;
uint256 reservedMinTokensIndex;
uint256 reservedMaxTokensIndex;
uint setFinalSupplyTimeAfterMint;
address randomizerContract;
IRandomizer randomizer;
}
// mapping of collectionAdditionalData structmapping (uint256=> collectionAdditonalDataStructure) private collectionAdditionalData;
// checks if a collection was createdmapping (uint256=>bool) private isCollectionCreated;
// checks if data on a collection were addedmapping (uint256=>bool) private wereDataAdded;
// maps tokends ids with collectionsidsmapping (uint256=>uint256) private tokenIdsToCollectionIds;
// stores the token hash generated by randomizer contractsmapping(uint256=>bytes32) private tokenToHash;
// amount of minted tokens per address per collection during public salemapping (uint256=>mapping (address=>uint256)) private tokensMintedPerAddress;
// amount of minted tokens per address per collection during allowlistmapping (uint256=>mapping (address=>uint256)) private tokensMintedAllowlistAddress;
// amount of tokens airdropped per address per collection mapping (uint256=>mapping (address=>uint256)) private tokensAirdropPerAddress;
// amount of burnt tokens per collectionmapping (uint256=>uint256) public burnAmount;
// metadata view (offchain/onchain)mapping (uint256=>bool) public onchainMetadata;
// artist signature per collectionmapping (uint256=>string) public artistsSignatures;
// additional metadata per tokenmapping (uint256=>string) public tokenData;
// on-chain image URI and attributes per tokenmapping (uint256=>string[2]) private tokenImageAndAttributes;
// collection lock status (status cannot revert) mapping (uint256=>bool) private collectionFreeze;
// checks if an artist signed its collectionmapping (uint256=>bool) public artistSigned;
// external contracts declaration
INextGenAdmins private adminsContract;
IDependencyRegistry private dependencyRegistry;
addresspublic minterContract;
// eventseventCollectionCreated(uint256indexed _collectionID);
// constructorconstructor(stringmemory name, stringmemory symbol, address _adminsContract, address _dependencyRegistry) ERC721(name, symbol) {
adminsContract = INextGenAdmins(_adminsContract);
dependencyRegistry = IDependencyRegistry(_dependencyRegistry);
newCollectionIndex = newCollectionIndex +1;
_setDefaultRoyalty(0xC8ed02aFEBD9aCB14c33B5330c803feacAF01377, 690);
}
// certain functions can only be called by a global or function adminmodifierFunctionAdminRequired(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 adminmodifierCollectionAdminRequired(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 create a CollectionfunctioncreateCollection(stringmemory _collectionName, stringmemory _collectionArtist, stringmemory _collectionDescription, stringmemory _collectionWebsite, stringmemory _collectionLicense, stringmemory _collectionBaseURI, stringmemory _collectionLibrary, bytes32 _collectionDependencyScript, string[] memory _collectionScript) publicFunctionAdminRequired(this.createCollection.selector) {
collectionInfo[newCollectionIndex].collectionName = _collectionName;
collectionInfo[newCollectionIndex].collectionArtist = _collectionArtist;
collectionInfo[newCollectionIndex].collectionDescription = _collectionDescription;
collectionInfo[newCollectionIndex].collectionWebsite = _collectionWebsite;
collectionInfo[newCollectionIndex].collectionLicense = _collectionLicense;
collectionInfo[newCollectionIndex].collectionBaseURI = _collectionBaseURI;
collectionInfo[newCollectionIndex].collectionLibrary = _collectionLibrary;
collectionInfo[newCollectionIndex].collectionDependencyScript = _collectionDependencyScript;
collectionInfo[newCollectionIndex].collectionScript = _collectionScript;
isCollectionCreated[newCollectionIndex] =true;
emit CollectionCreated(newCollectionIndex);
newCollectionIndex = newCollectionIndex +1;
}
// function to add/modify the additional data of a collection// once a collection is created and total supply is set it cannot changefunctionsetCollectionData(uint256 _collectionID, address _collectionArtistAddress, uint256 _maxCollectionPurchases, uint256 _collectionTotalSupply, uint _setFinalSupplyTimeAfterMint) publicCollectionAdminRequired(_collectionID, this.setCollectionData.selector) {
require((isCollectionCreated[_collectionID] ==true) && (collectionFreeze[_collectionID] ==false) && (_collectionTotalSupply <=10000000000), "err/freezed");
if (collectionAdditionalData[_collectionID].collectionTotalSupply ==0) {
collectionAdditionalData[_collectionID].collectionArtistAddress = _collectionArtistAddress;
collectionAdditionalData[_collectionID].maxCollectionPurchases = _maxCollectionPurchases;
collectionAdditionalData[_collectionID].collectionCirculationSupply =0;
collectionAdditionalData[_collectionID].collectionTotalSupply = _collectionTotalSupply;
collectionAdditionalData[_collectionID].setFinalSupplyTimeAfterMint = _setFinalSupplyTimeAfterMint;
collectionAdditionalData[_collectionID].reservedMinTokensIndex = (_collectionID *10000000000);
collectionAdditionalData[_collectionID].reservedMaxTokensIndex = (_collectionID *10000000000) + _collectionTotalSupply -1;
wereDataAdded[_collectionID] =true;
} elseif (artistSigned[_collectionID] ==false) {
collectionAdditionalData[_collectionID].collectionArtistAddress = _collectionArtistAddress;
collectionAdditionalData[_collectionID].maxCollectionPurchases = _maxCollectionPurchases;
collectionAdditionalData[_collectionID].setFinalSupplyTimeAfterMint = _setFinalSupplyTimeAfterMint;
} else {
collectionAdditionalData[_collectionID].maxCollectionPurchases = _maxCollectionPurchases;
collectionAdditionalData[_collectionID].setFinalSupplyTimeAfterMint = _setFinalSupplyTimeAfterMint;
}
}
// set a randomizer contract on a collectionfunctionaddRandomizer(uint256 _collectionID, address _randomizerContract) publicFunctionAdminRequired(this.addRandomizer.selector) {
require(IRandomizer(_randomizerContract).isRandomizerContract() ==true, "Contract is not Randomizer");
collectionAdditionalData[_collectionID].randomizerContract = _randomizerContract;
collectionAdditionalData[_collectionID].randomizer = IRandomizer(_randomizerContract);
}
// airdrop (function is called from minter contract)functionairDropTokens(uint256 mintIndex, address _recipient, stringmemory _tokenData, uint256 _saltfun_o, uint256 _collectionID) external{
require(msg.sender== minterContract, "Caller is not the Minter Contract");
collectionAdditionalData[_collectionID].collectionCirculationSupply = collectionAdditionalData[_collectionID].collectionCirculationSupply +1;
if (collectionAdditionalData[_collectionID].collectionTotalSupply >= collectionAdditionalData[_collectionID].collectionCirculationSupply) {
tokensAirdropPerAddress[_collectionID][_recipient] = tokensAirdropPerAddress[_collectionID][_recipient] +1;
_mintProcessing(mintIndex, _recipient, _tokenData, _collectionID, _saltfun_o);
} else {
revert("Supply reached");
}
}
// mint (function is called from minter contract)functionmint(uint256 mintIndex, address _mintingAddress , address _mintTo, stringmemory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint256 phase) external{
require(msg.sender== minterContract, "Caller is not the Minter Contract");
collectionAdditionalData[_collectionID].collectionCirculationSupply = collectionAdditionalData[_collectionID].collectionCirculationSupply +1;
if (collectionAdditionalData[_collectionID].collectionTotalSupply >= collectionAdditionalData[_collectionID].collectionCirculationSupply) {
if (phase ==1) {
tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] +1;
} else {
tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] +1;
}
_mintProcessing(mintIndex, _mintTo, _tokenData, _collectionID, _saltfun_o);
} else {
revert("Supply reached");
}
}
// burn functionfunctionburn(uint256 _collectionID, uint256 _tokenId) public{
require(_isApprovedOrOwner(_msgSender(), _tokenId), "ERC721: caller is not token owner or approved");
require ((_tokenId >= collectionAdditionalData[_collectionID].reservedMinTokensIndex) && (_tokenId <= collectionAdditionalData[_collectionID].reservedMaxTokensIndex), "id err");
_burn(_tokenId);
burnAmount[_collectionID] = burnAmount[_collectionID] +1;
}
// burn to mint (function is called from minter contract)functionburnToMint(uint256 mintIndex, uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o, address burner) external{
require(msg.sender== minterContract, "Caller is not the Minter Contract");
require(_isApprovedOrOwner(burner, _tokenId), "ERC721: caller is not token owner or approved");
collectionAdditionalData[_mintCollectionID].collectionCirculationSupply = collectionAdditionalData[_mintCollectionID].collectionCirculationSupply +1;
if (collectionAdditionalData[_mintCollectionID].collectionTotalSupply >= collectionAdditionalData[_mintCollectionID].collectionCirculationSupply) {
address owner = ownerOf(_tokenId);
_burn(_tokenId);
burnAmount[_burnCollectionID] = burnAmount[_burnCollectionID] +1;
tokensMintedPerAddress[_mintCollectionID][owner] = tokensMintedPerAddress[_mintCollectionID][owner] +1;
_mintProcessing(mintIndex, owner, tokenData[_tokenId], _mintCollectionID, _saltfun_o);
} else {
revert("Supply reached");
}
}
// mint processingfunction_mintProcessing(uint256 _mintIndex, address _recipient, stringmemory _tokenData, uint256 _collectionID, uint256 _saltfun_o) internal{
tokenData[_mintIndex] = _tokenData;
tokenIdsToCollectionIds[_mintIndex] = _collectionID;
_safeMint(_recipient, _mintIndex);
collectionAdditionalData[_collectionID].randomizer.calculateTokenHash(_collectionID, _mintIndex, _saltfun_o);
}
// Additional setter functions// function to update a collection's infofunctionupdateCollectionInfo(uint256 _collectionID, stringmemory _newCollectionName, stringmemory _newCollectionArtist, stringmemory _newCollectionDescription, stringmemory _newCollectionWebsite, stringmemory _newCollectionLicense, stringmemory _newCollectionBaseURI, stringmemory _newCollectionLibrary, bytes32 _newCollectionDependencyScript, uint256 _index, string[] memory _newCollectionScript) publicCollectionAdminRequired(_collectionID, this.updateCollectionInfo.selector) {
require((isCollectionCreated[_collectionID] ==true) && (collectionFreeze[_collectionID] ==false), "Not allowed");
if (_index ==1000000) {
collectionInfo[_collectionID].collectionName = _newCollectionName;
collectionInfo[_collectionID].collectionArtist = _newCollectionArtist;
collectionInfo[_collectionID].collectionDescription = _newCollectionDescription;
collectionInfo[_collectionID].collectionWebsite = _newCollectionWebsite;
collectionInfo[_collectionID].collectionLicense = _newCollectionLicense;
collectionInfo[_collectionID].collectionLibrary = _newCollectionLibrary;
collectionInfo[_collectionID].collectionDependencyScript = _newCollectionDependencyScript;
collectionInfo[_collectionID].collectionScript = _newCollectionScript;
} elseif (_index ==999999) {
collectionInfo[_collectionID].collectionBaseURI = _newCollectionBaseURI;
} else {
collectionInfo[_collectionID].collectionScript[_index] = _newCollectionScript[0];
}
}
// function that is used by artists for signingfunctionartistSignature(uint256 _collectionID, stringmemory _signature) public{
require(msg.sender== collectionAdditionalData[_collectionID].collectionArtistAddress && artistSigned[_collectionID] ==false, "Not artist/Signed");
artistsSignatures[_collectionID] = _signature;
artistSigned[_collectionID] =true;
}
// function to change the metadata view of a collectionfunctionchangeMetadataView(uint256 _collectionID, bool _status) publicCollectionAdminRequired(_collectionID, this.changeMetadataView.selector) {
require((isCollectionCreated[_collectionID] ==true) && (collectionFreeze[_collectionID] ==false), "Not allowed");
onchainMetadata[_collectionID] = _status;
}
// function to change the token data of a tokenfunctionchangeTokenData(uint256 _tokenId, stringmemory newData) publicFunctionAdminRequired(this.changeTokenData.selector) {
require(collectionFreeze[tokenIdsToCollectionIds[_tokenId]] ==false, "Data frozen");
_requireMinted(_tokenId);
tokenData[_tokenId] = newData;
}
// function to store onchain an imageURI and attributes for a tokenfunctionupdateImagesAndAttributes(uint256[] memory _tokenId, string[] memory _images, string[] memory _attributes) publicFunctionAdminRequired(this.updateImagesAndAttributes.selector) {
require((_tokenId.length== _images.length) && (_images.length== _attributes.length) , "inv len");
for (uint256 x; x < _tokenId.length; x++) {
require(collectionFreeze[tokenIdsToCollectionIds[_tokenId[x]]] ==false, "Data frozen");
_requireMinted(_tokenId[x]);
tokenImageAndAttributes[_tokenId[x]][0] = _images[x];
tokenImageAndAttributes[_tokenId[x]][1] = _attributes[x];
}
}
// function to lock collection, this action connot be revertedfunctionfreezeCollection(uint256 _collectionID) publicFunctionAdminRequired(this.freezeCollection.selector) {
require(block.timestamp> IMinterContract(minterContract).getEndTime(_collectionID) && IMinterContract(minterContract).getEndTime(_collectionID) !=0&& wereDataAdded[_collectionID] ==true);
collectionFreeze[_collectionID] =true;
}
// function to set the tokenHash (this function is called only from randomizer contracts)functionsetTokenHash(uint256 _collectionID, uint256 _mintIndex, bytes32 _hash) external{
require(msg.sender== collectionAdditionalData[_collectionID].randomizerContract);
require(tokenToHash[_mintIndex] ==0x0000000000000000000000000000000000000000000000000000000000000000);
tokenToHash[_mintIndex] = _hash;
}
// function to set final supply, this applies only for unminted collections and will adjust totalSupply = circulatingSupplyfunctionsetFinalSupply(uint256 _collectionID) publicFunctionAdminRequired(this.setFinalSupply.selector) {
require (block.timestamp> IMinterContract(minterContract).getEndTime(_collectionID) + collectionAdditionalData[_collectionID].setFinalSupplyTimeAfterMint, "Time has not passed");
collectionAdditionalData[_collectionID].collectionTotalSupply = collectionAdditionalData[_collectionID].collectionCirculationSupply;
collectionAdditionalData[_collectionID].reservedMaxTokensIndex = (_collectionID *10000000000) + collectionAdditionalData[_collectionID].collectionTotalSupply -1;
}
// function to update the admin, minter or dependency contract// 1. admin contract 2. minter contract 3. dependency registry contractfunctionupdateContracts(uint8 _opt, address _newContract) publicFunctionAdminRequired(this.updateContracts.selector) {
if (_opt ==1) {
require(INextGenAdmins(_newContract).isAdminContract() ==true, "Not Admin");
adminsContract = INextGenAdmins(_newContract);
} elseif (_opt ==2) {
require(IMinterContract(_newContract).isMinterContract() ==true, "Not Minter");
minterContract = _newContract;
} else {
dependencyRegistry = IDependencyRegistry(_newContract);
}
}
// Retrieve Functions// function that overrides supportInterfacefunctionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC721Enumerable, ERC2981) returns (bool) {
returnsuper.supportsInterface(interfaceId);
}
// function that return the tokenURIfunctiontokenURI(uint256 tokenId) publicviewvirtualoverridereturns (stringmemory) {
_requireMinted(tokenId);
if (onchainMetadata[tokenIdsToCollectionIds[tokenId]] ==false&& tokenToHash[tokenId] !=0x0000000000000000000000000000000000000000000000000000000000000000) {
stringmemory baseURI = collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionBaseURI;
returnbytes(baseURI).length>0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
} elseif (onchainMetadata[tokenIdsToCollectionIds[tokenId]] ==false&& tokenToHash[tokenId] ==0x0000000000000000000000000000000000000000000000000000000000000000) {
stringmemory baseURI = collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionBaseURI;
returnbytes(baseURI).length>0 ? string(abi.encodePacked(baseURI, "pending")) : "";
}
else {
stringmemory b64 = Base64.encode(abi.encodePacked("<html><head></head><body><script src=\"",collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionLibrary,"\"></script><script>",retrieveGenerativeScript(tokenId),"</script></body></html>"));
stringmemory _uri =string(abi.encodePacked("data:application/json;utf8,{\"name\":\"",getTokenName(tokenId),"\",\"description\":\"",collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionDescription,"\",\"image\":\"",tokenImageAndAttributes[tokenId][0],"\",\"attributes\":[",tokenImageAndAttributes[tokenId][1],"],\"animation_url\":\"data:text/html;base64,",b64,"\"}"));
return _uri;
}
}
// function to retrieve the name attributefunctiongetTokenName(uint256 tokenId) privateviewreturns(stringmemory) {
uint256 tok = tokenId - collectionAdditionalData[tokenIdsToCollectionIds[tokenId]].reservedMinTokensIndex;
returnstring(abi.encodePacked(collectionInfo[viewColIDforTokenID(tokenId)].collectionName, " #" ,tok.toString()));
}
// function to retrieve the collection freeze statusfunctioncollectionFreezeStatus(uint256 _collectionID) publicviewreturns(bool){
return collectionFreeze[_collectionID];
}
// function to return the collection id given a token idfunctionviewColIDforTokenID(uint256 _tokenid) publicviewreturns (uint256) {
return(tokenIdsToCollectionIds[_tokenid]);
}
// function to retrieve if data were added on a collectionfunctionretrievewereDataAdded(uint256 _collectionID) externalviewreturns(bool){
return wereDataAdded[_collectionID];
}
// function to return the min index id of a collectionfunctionviewTokensIndexMin(uint256 _collectionID) externalviewreturns (uint256) {
return(collectionAdditionalData[_collectionID].reservedMinTokensIndex);
}
// function to return the max index id of a collectionfunctionviewTokensIndexMax(uint256 _collectionID) externalviewreturns (uint256) {
return(collectionAdditionalData[_collectionID].reservedMaxTokensIndex);
}
// function to return the circ supply of a collectionfunctionviewCirSupply(uint256 _collectionID) externalviewreturns (uint256) {
return(collectionAdditionalData[_collectionID].collectionCirculationSupply);
}
// function to return max allowance per address during public salefunctionviewMaxAllowance(uint256 _collectionID) externalviewreturns (uint256) {
return(collectionAdditionalData[_collectionID].maxCollectionPurchases);
}
// function to return tokens minted per address during allowlistfunctionretrieveTokensMintedALPerAddress(uint256 _collectionID, address _address) externalviewreturns(uint256) {
return (tokensMintedAllowlistAddress[_collectionID][_address]);
}
// function to return tokens minted per address during publicfunctionretrieveTokensMintedPublicPerAddress(uint256 _collectionID, address _address) externalviewreturns(uint256) {
return (tokensMintedPerAddress[_collectionID][_address]);
}
// function to retrieve the airdropped tokens per address functionretrieveTokensAirdroppedPerAddress(uint256 _collectionID, address _address) publicviewreturns(uint256) {
return (tokensAirdropPerAddress[_collectionID][_address]);
}
// function to return the artist's addressfunctionretrieveArtistAddress(uint256 _collectionID) externalviewreturns(address) {
return (collectionAdditionalData[_collectionID].collectionArtistAddress);
}
// function to retrieve a collection's infofunctionretrieveCollectionInfo(uint256 _collectionID) publicviewreturns(stringmemory, stringmemory, stringmemory, stringmemory, stringmemory, stringmemory){
return (collectionInfo[_collectionID].collectionName, collectionInfo[_collectionID].collectionArtist, collectionInfo[_collectionID].collectionDescription, collectionInfo[_collectionID].collectionWebsite, collectionInfo[_collectionID].collectionLicense, collectionInfo[_collectionID].collectionBaseURI);
}
// function to retrieve the library and script of a collectionfunctionretrieveCollectionLibraryAndScript(uint256 _collectionID) publicviewreturns(stringmemory, bytes32, string[] memory){
return (collectionInfo[_collectionID].collectionLibrary, collectionInfo[_collectionID].collectionDependencyScript, collectionInfo[_collectionID].collectionScript);
}
// function to retrieve the additional data of a CollectionfunctionretrieveCollectionAdditionalData(uint256 _collectionID) publicviewreturns(address, uint256, uint256, uint256, uint, address){
return (collectionAdditionalData[_collectionID].collectionArtistAddress, collectionAdditionalData[_collectionID].maxCollectionPurchases, collectionAdditionalData[_collectionID].collectionCirculationSupply, collectionAdditionalData[_collectionID].collectionTotalSupply, collectionAdditionalData[_collectionID].setFinalSupplyTimeAfterMint, collectionAdditionalData[_collectionID].randomizerContract);
}
// function to retrieve the token hashfunctionretrieveTokenHash(uint256 _tokenid) publicviewreturns(bytes32){
return (tokenToHash[_tokenid]);
}
// function to retrieve the generative script of a tokenfunctionretrieveGenerativeScript(uint256 tokenId) publicviewreturns(stringmemory) {
_requireMinted(tokenId);
stringmemory scripttext;
for (uint256 i=0; i < collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionScript.length; i++) {
scripttext =string(abi.encodePacked(scripttext, collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionScript[i]));
}
returnstring(abi.encodePacked("let hash='",Strings.toHexString(uint256(tokenToHash[tokenId]), 32),"';let tokenId=",tokenId.toString(),";let tokenData=[",tokenData[tokenId],"]",";let dependencyScript='",retrieveDependencyScript(tokenId),"';", scripttext));
}
// function to retrieve on-chain dependency scriptfunctionretrieveDependencyScript(uint256 tokenId) privateviewreturns(stringmemory) {
stringmemory scripttext;
for (uint256 i=0; i < dependencyRegistry.getDependencyScriptCount(collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionDependencyScript); i++) {
scripttext =string(abi.encodePacked(scripttext, dependencyRegistry.getDependencyScript(collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionDependencyScript, i)));
}
returnstring(abi.encodePacked(scripttext));
}
// function to retrieve the supply of a collectionfunctiontotalSupplyOfCollection(uint256 _collectionID) publicviewreturns (uint256) {
return (collectionAdditionalData[_collectionID].collectionCirculationSupply - burnAmount[_collectionID]);
}
// function to retrieve the token image uri and the attributes stored on-chain for a token id.functionretrievetokenImageAndAttributes(uint256 _tokenId) publicviewreturns(stringmemory, stringmemory) {
return (tokenImageAndAttributes[_tokenId][0],tokenImageAndAttributes[_tokenId][1]);
}
}
Contract Source Code
File 20 of 22: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)pragmasolidity ^0.8.0;/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/import"./Context.sol";
abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 21 of 22: SignedMath.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)pragmasolidity ^0.8.0;/**
* @dev Standard signed math utilities missing in the Solidity language.
*/librarySignedMath{
/**
* @dev Returns the largest of two signed numbers.
*/functionmax(int256 a, int256 b) internalpurereturns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/functionmin(int256 a, int256 b) internalpurereturns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/functionaverage(int256 a, int256 b) internalpurereturns (int256) {
// Formula from the book "Hacker's Delight"int256 x = (a & b) + ((a ^ b) >>1);
return x + (int256(uint256(x) >>255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/functionabs(int256 n) internalpurereturns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`returnuint256(n >=0 ? n : -n);
}
}
}
Contract Source Code
File 22 of 22: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/import"./Math.sol";
import"./SignedMath.sol";
libraryStrings{
bytes16privateconstant _SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/functiontoString(int256 value) internalpurereturns (stringmemory) {
returnstring(abi.encodePacked(value <0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/functionequal(stringmemory a, stringmemory b) internalpurereturns (bool) {
returnkeccak256(bytes(a)) ==keccak256(bytes(b));
}
}