Overview
APE Balance
0 APE
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
CollectionMetadataRenderer
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {StringsUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; import {IERC721MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC721MetadataUpgradeable.sol"; import {IMetadataRenderer} from "../interfaces/IMetadataRenderer.sol"; import {DynamicMetadataRenderer} from "./DynamicMetadataRenderer.sol"; import {MetadataRenderAdminCheck} from "./MetadataRenderAdminCheck.sol"; /// @notice Collection metadata system contract CollectionMetadataRenderer is IMetadataRenderer, MetadataRenderAdminCheck { error MetadataFrozen(); /// Event to mark updated metadata information event MetadataUpdated(address indexed target, string metadataBase, string metadataExtension, string contractURI, uint256 freezeAt); event DynamicMetadataUpdated(address indexed target, string imageURI, string animationURI); /// @notice Hash to mark updated provenance hash event ProvenanceHashUpdated(address indexed target, bytes32 provenanceHash); /// @notice Struct to store metadata info and update data struct MetadataURIInfo { string base; string extension; string contractURI; uint256 freezeAt; } struct DynamicMetadataInfo { string description; string imageURI; string animationURI; } /// @notice NFT metadata by contract mapping(address => MetadataURIInfo) public metadataBaseByContract; /// @notice Dynamic NFT metadata by contract mapping(address => DynamicMetadataInfo) public dynamicMetadataInfoByContract; /// @notice Optional provenance hashes for NFT metadata by contract mapping(address => bytes32) public provenanceHashes; /// @notice Standard init for collection metadata from root collection contract /// @param metadataBase passed in for initialization /// @param dynamicTokenData passed in for initialization function initializeWithData(bytes memory metadataBase, bytes memory dynamicTokenData) external { if (metadataBase.length > 0) { (string memory initialBaseURI, string memory initialContractURI) = abi.decode(metadataBase, (string, string)); _updateMetadataDetails(msg.sender, initialBaseURI, "", initialContractURI, 0); } if (dynamicTokenData.length > 0) { (string memory description, string memory imageURI, string memory animationURI) = abi.decode(dynamicTokenData, (string, string, string)); _updateDynamicMetadataInfo(msg.sender, description, imageURI, animationURI); } } /// @notice Update the provenance hash (optional) for a given nft /// @param target target address to update /// @param provenanceHash provenance hash to set function updateProvenanceHash(address target, bytes32 provenanceHash) external requireSenderAdmin(target) { provenanceHashes[target] = provenanceHash; emit ProvenanceHashUpdated(target, provenanceHash); } /// @notice Update metadata base URI and contract URI /// @param target target contract to update metadata for /// @param metadataBaseURI new base URI /// @param newContractURI new contract URI (can be an empty string) function updateMetadataBase(address target, string memory metadataBaseURI, string memory newContractURI) external requireSenderAdmin(target) { _updateMetadataDetails(target, metadataBaseURI, "", newContractURI, 0); } /// @notice Update metadata base URI, extension, contract URI and freezing details /// @param target target contract to update metadata for /// @param metadataBase new base URI to update metadata with /// @param metadataExtension new extension to append to base metadata URI /// @param freezeAt time to freeze the contract metadata at (set to 0 to disable) /// @param newContractURI new contract URI (can be an empty string) function updateMetadataBaseWithDetails( address target, string memory metadataBase, string memory metadataExtension, string memory newContractURI, uint256 freezeAt ) external requireSenderAdmin(target) { _updateMetadataDetails(target, metadataBase, metadataExtension, newContractURI, freezeAt); } /// @notice Internal metadata update function /// @param metadataBase Bbase URI to update metadata with /// @param metadataExtension extension URI to append to base metadata URI /// @param freezeAt timestamp to freeze metadata (set to 0 to disable freezing) function _updateMetadataDetails( address target, string memory metadataBase, string memory metadataExtension, string memory newContractURI, uint256 freezeAt ) internal { uint256 contractFreezeTime = metadataBaseByContract[target].freezeAt; if (contractFreezeTime != 0 && contractFreezeTime <= block.timestamp) { revert MetadataFrozen(); } metadataBaseByContract[target] = MetadataURIInfo({base: metadataBase, extension: metadataExtension, contractURI: newContractURI, freezeAt: freezeAt}); emit MetadataUpdated({ target: target, metadataBase: metadataBase, metadataExtension: metadataExtension, contractURI: newContractURI, freezeAt: freezeAt }); } function updateDynamicMetadataInfo( address target, string memory description, string memory imageURI, string memory animationURI ) external requireSenderAdmin(target) { _updateDynamicMetadataInfo(target, description, imageURI, animationURI); } function _updateDynamicMetadataInfo( address target, string memory description, string memory imageURI, string memory animationURI ) internal { dynamicMetadataInfoByContract[target] = DynamicMetadataInfo({ description: description, imageURI: imageURI, animationURI: animationURI }); emit DynamicMetadataUpdated({target: target, imageURI: imageURI, animationURI: animationURI}); } /// @notice A contract URI for the given collection contract /// @dev reverts if a contract uri is not provided /// @return contract uri for the contract metadata function contractURI() external view override returns (string memory) { string memory uri = metadataBaseByContract[msg.sender].contractURI; if (bytes(uri).length == 0) revert(); return uri; } /// @notice A token URI for the given collection contract /// @dev reverts if a contract uri is not set /// @return token URI for the given token ID and contract (set by msg.sender) function tokenURI(uint256 tokenId, bool revealed) external view override returns (string memory) { if (!revealed) { return dynamicTokenURI(tokenId); } MetadataURIInfo memory info = metadataBaseByContract[msg.sender]; if (bytes(info.base).length == 0) revert(); return string(abi.encodePacked(info.base, StringsUpgradeable.toString(tokenId), info.extension)); } /// @notice A token URI for the given collection contract, handle when image is the same, ex, pre-reveal /// @dev reverts if a contract uri is not set /// @return token URI for the given token ID and contract (set by msg.sender) function dynamicTokenURI(uint256 tokenId) public view returns (string memory) { DynamicMetadataInfo memory info = dynamicMetadataInfoByContract[msg.sender]; address target = msg.sender; if (bytes(info.imageURI).length == 0 && bytes(info.animationURI).length == 0) revert(); return DynamicMetadataRenderer.createMetadata({ name: IERC721MetadataUpgradeable(target).name(), description: info.description, imageURI: info.imageURI, animationURI: info.animationURI, isEdition: false, tokenId: tokenId }); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(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"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../token/ERC721/extensions/IERC721MetadataUpgradeable.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; interface IMetadataRenderer { function tokenURI(uint256, bool) external view returns (string memory); function contractURI() external view returns (string memory); function initializeWithData(bytes memory metadataBase, bytes memory dynamicTokenData) external; function updateMetadataBase( address collection, string memory baseURI, string memory metadataURI ) external; function updateMetadataBaseWithDetails( address collection, string memory baseURI, string memory extension, string memory metadataURI, uint256 freezeAt ) external; function dynamicTokenURI(uint256) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {Base64} from "@openzeppelin/contracts/utils/Base64.sol"; /// NFT metadata library for dynamically render metadata library DynamicMetadataRenderer { /// Generate metadata from storage information as base64-json blob /// Combines the media data and metadata /// @param name Name of NFT in metadata /// @param description Description of NFT in metadata /// @param imageURI URI of image to render for edition /// @param animationURI URI of animation to render for edition /// @param isEdition collection type /// @param tokenId Token ID for specific token function createMetadata( string memory name, string memory description, string memory imageURI, string memory animationURI, bool isEdition, uint256 tokenId ) internal pure returns (string memory) { string memory _tokenMediaData = tokenMediaData(imageURI, animationURI); bytes memory json = createMetadataJSON(name, description, _tokenMediaData, isEdition, tokenId); return encodeMetadataJSON(json); } /// Function to create the metadata json string for the nft edition /// @param name Name of NFT in metadata /// @param description Description of NFT in metadata /// @param mediaData Data for media to include in json object /// @param isEdition different format for edition metadata /// @param tokenId Token ID for specific token function createMetadataJSON( string memory name, string memory description, string memory mediaData, bool isEdition, uint256 tokenId ) internal pure returns (bytes memory) { if (isEdition) { return abi.encodePacked( '{"name": "', name, " #", Strings.toString(tokenId), '", "', 'description": "', description, '", "', mediaData, ',' '"properties": {"number": ', Strings.toString(tokenId), ', "name": "', name, '"}}' ); } else { return abi.encodePacked('{"name": "', name, " #", Strings.toString(tokenId), '", "', 'description": "', description, '", "', mediaData, "}"); } } function encodeContractURIJSON( string memory name, string memory description, string memory imageURI, string memory animationURI, uint256 royaltyBPS, address royaltyRecipient ) internal pure returns (string memory) { bytes memory imageSpace = bytes(""); if (bytes(imageURI).length > 0) { imageSpace = abi.encodePacked('", "image": "', imageURI); } bytes memory animationSpace = bytes(""); if (bytes(animationURI).length > 0) { animationSpace = abi.encodePacked('", "animation_url": "', animationURI); } return string( encodeMetadataJSON( abi.encodePacked( '{"name": "', name, '", "description": "', description, // this is for opensea since they don't respect ERC2981 right now '", "seller_fee_basis_points": ', Strings.toString(royaltyBPS), ', "fee_recipient": "', Strings.toHexString(uint256(uint160(royaltyRecipient)), 20), imageSpace, animationSpace, '"}' ) ) ); } /// Encodes the argument json bytes into base64-data uri format /// @param json Raw json to base64 and turn into a data-uri function encodeMetadataJSON(bytes memory json) internal pure returns (string memory) { return string(abi.encodePacked("data:application/json;base64,", Base64.encode(json))); } /// Generates edition metadata from storage information as base64-json blob /// Combines the media data and metadata /// @param imageUrl URL of image to render for edition /// @param animationUrl URL of animation to render for edition function tokenMediaData(string memory imageUrl, string memory animationUrl) internal pure returns (string memory) { bool hasImage = bytes(imageUrl).length > 0; bool hasAnimation = bytes(animationUrl).length > 0; if (hasImage && hasAnimation) { return string(abi.encodePacked('image": "', imageUrl, '", "animation_url": "', animationUrl, '"')); } if (hasImage) { return string(abi.encodePacked('image": "', imageUrl, '"')); } if (hasAnimation) { return string(abi.encodePacked('animation_url": "', animationUrl, '"')); } return ""; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IERC721Collection} from "../interfaces/IERC721Collection.sol"; contract MetadataRenderAdminCheck { error Access_OnlyAdmin(); /// @notice Modifier to require the sender to be an admin /// @param target address that the user wants to modify modifier requireSenderAdmin(address target) { if (target != msg.sender && !IERC721Collection(target).isAdmin(msg.sender)) { revert Access_OnlyAdmin(); } _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (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. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (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. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (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 product uint256 prod1; // Most significant 256 bits of the product assembly { 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) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (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). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // 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. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (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. */ function log2(uint256 value) internal pure returns (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. */ function log2(uint256 value, Rounding rounding) internal pure returns (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. */ function log10(uint256 value) internal pure returns (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. */ function log10(uint256 value, Rounding rounding) internal pure returns (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. */ function log256(uint256 value) internal pure returns (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 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721Upgradeable.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721MetadataUpgradeable is IERC721Upgradeable { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(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"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) pragma solidity ^0.8.0; /** * @dev Provides a set of functions to operate with Base64 strings. * * _Available since v4.5._ */ library Base64 { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * 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 memory string memory 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 chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 32) // Run over the input, 3 bytes at a time for { 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 bits mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(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 end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IMetadataRenderer} from "../interfaces/IMetadataRenderer.sol"; /// @notice Interface for Freee Collection contract interface IERC721Collection { // Enums /// @notice Phase type enum PhaseType { Public, Presale, Airdrop, AdminMint } // Access errors /// @notice Only admin can access this function error Access_OnlyAdmin(); /// @notice Missing the given role or admin access error Access_MissingRoleOrAdmin(bytes32 role); /// @notice Withdraw is not allowed by this user error Access_WithdrawNotAllowed(); /// @notice Cannot withdraw funds due to ETH send failure. error Withdraw_FundsSendFailure(); /// @notice Call to external metadata renderer failed. error ExternalMetadataRenderer_CallFailed(); // Sale/Purchase errors /// @notice Sale is inactive error Sale_Inactive(); /// @notice Presale is inactive error Presale_Inactive(); /// @notice Presale invalid, out of range error Presale_Invalid(); /// @notice Exceed presale stage supply error Presale_ExceedStageSupply(); /// @notice Presale merkle root is invalid error Presale_MerkleNotApproved(); /// @notice Wrong price for purchase error Purchase_WrongPrice(uint256 correctPrice); /// @notice NFT sold out error Mint_SoldOut(); /// @notice Too many purchase for address error Purchase_TooManyForAddress(); /// @notice Too many presale for address error Presale_TooManyForAddress(); /// @notice Collection already revealed error Collection_Aready_Revealed(); /// @notice Trading locked before mint out error Collection_TradingLocked(); // Admin errors /// @notice Presale stage out of supported range error Setup_Presale_StageOutOfRange(); /// @notice Royalty percentage too high error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS); /// @notice invalid collection size when update error Admin_InvalidCollectionSize(); /// @notice Event emitted for mint fee payout /// @param mintFeeAmount amount of the mint fee /// @param mintFeeRecipient recipient of the mint fee /// @param success if the payout succeeded event MintFeePayout(uint256 mintFeeAmount, address mintFeeRecipient, bool success); /// @notice Event emitted for each sale /// @param phase phase of the sale /// @param to address sale was made to /// @param quantity quantity of the minted nfts /// @param pricePerToken price for each token /// @param firstPurchasedTokenId first purchased token ID (to get range add to quantity for max) /// @param presaleStage stageIndex of presale stage if applicable, else return 0 event Sale(PhaseType phase, address indexed to, uint256 indexed quantity, uint256 indexed pricePerToken, uint256 firstPurchasedTokenId, uint256 presaleStage); /// @notice Event emitted for each sale /// @param sender address sale was made to /// @param tokenContract address of the token contract /// @param tokenId first purchased token ID (to get range add to quantity for max) /// @param quantity quantity of the minted nfts /// @param comment caller provided comment event MintComment(address indexed sender, address indexed tokenContract, uint256 indexed tokenId, uint256 quantity, string comment); /// @notice Contract has been configured and published /// @param changedBy Changed by user event ContractStatusChanged(address indexed changedBy); /// @notice Sales configuration has been changed /// @dev To access new sales configuration, use getter function. /// @param changedBy Changed by user event PublicSaleConfigChanged(address indexed changedBy); /// @notice Presale config changed /// @param changedBy changed by user event PresaleConfigChanged(address indexed changedBy); /// @notice Collection size reduced /// @param changedBy changed by user /// @param newSize new collection size event CollectionSizeReduced(address indexed changedBy, uint64 newSize); /// @notice event emit when user change the lock trading func /// @param changedBy changed by user /// @param status new status event LockTradingStatusChanged(address indexed changedBy, bool status); /// @notice Event emitted when the royalty percentage changed /// @param changedBy address that change the royalty /// @param newPercentage new royalty percentage /// @param newRecipient new royalty recipient event RoyaltyChanged(address indexed changedBy, uint256 newPercentage, address newRecipient); /// @notice Event emitted when the funds recipient is changed /// @param newAddress new address for the funds recipient /// @param changedBy address that the recipient is changed by event FundsRecipientChanged(address indexed newAddress, address indexed changedBy); /// @notice Event emitted when the funds are withdrawn from the minting contract /// @param withdrawnBy address that issued the withdraw /// @param withdrawnTo address that the funds were withdrawn to /// @param amount amount that was withdrawn /// @param feeRecipient user getting withdraw fee (if any) /// @param feeAmount amount of the fee getting sent (if any) event FundsWithdrawn(address indexed withdrawnBy, address indexed withdrawnTo, uint256 amount, address feeRecipient, uint256 feeAmount); /// @notice Collection dynamic metadata changed /// @param changedBy address that changed the info event DynamicMetadataChanged(address changedBy); /// @notice Collection has been revealed /// @param revealedBy Revealed by user event CollectionRevealed(address indexed revealedBy); /// @notice Event emitted when metadata renderer is updated. /// @param sender address of the updater /// @param renderer new metadata renderer address event UpdatedMetadataRenderer(address sender, IMetadataRenderer renderer); /// @notice General configuration for NFT Minting and bookkeeping struct Configuration { /// @dev Metadata renderer IMetadataRenderer metadataRenderer; /// @dev Max supply of collection uint64 collectionSize; /// @dev Royalty amount in bps uint16 royaltyBPS; /// @dev Funds recipient for sale address payable fundsRecipient; /// @dev Royalty recipient for secondary sale address payable royaltyRecipient; /// @dev collection reveal status bool revealed; /// @dev lock trading before mint out bool lockBeforeMintOut; } /// @notice Public sale configuration /// @dev Uses 1 storage slot struct PublicSaleConfiguration { /// @dev Public sale price (max ether value > 1000 ether with this value) uint104 publicSalePrice; /// @dev Purchase mint limit per address (if set to 0 === unlimited mints) uint32 maxSalePurchasePerAddress; /// @dev uint64 type allows for dates into 292 billion years uint64 publicSaleStart; uint64 publicSaleEnd; /// @dev Whether public sale is disabled bool publicSaleDisabled; } /// @notice Presale stage configuration struct PresaleConfiguration { /// @notice Presale stage human readable name string presaleName; /// @notice Presale start timestamp uint64 presaleStart; /// @notice Presale end timestamp uint64 presaleEnd; /// @notice Presale price in ether uint104 presalePrice; /// @notice Purchase mint limit per address (if set to 0 === unlimited mints) uint32 presaleMaxPurchasePerAddress; /// @notice supply allocated for presale stage uint32 presaleSupply; /// @notice amount minted for presale stage uint32 presaleMinted; /// @notice Presale merkle root bytes32 presaleMerkleRoot; } /// @notice Return type of specific mint counts and details per address struct AddressMintDetails { /// Number of presale mints for each stage from the given address uint256[] presaleMintsByStage; /// Number of presale mints from the given address uint256 presaleMints; /// Number of public mints from the given address uint256 publicMints; /// Number of total mints from the given address uint256 totalMints; } /// @notice External purchase function (payable in eth) /// @param quantity to purchase /// @return first minted token ID function purchase(uint256 quantity) external payable returns (uint256); /// @notice External purchase presale function (takes a merkle proof and matches to root) (payable in eth) /// @param stageIndex targetted presale stage /// @param quantity to purchase /// @param maxQuantity can purchase (verified by merkle root) /// @param pricePerToken price per token allowed (verified by merkle root) /// @param merkleProof input for merkle proof leaf verified by merkle root /// @return first minted token ID function purchasePresale(uint256 stageIndex, uint256 quantity, uint256 maxQuantity, uint256 pricePerToken, bytes32[] memory merkleProof) external payable returns (uint256); /// @notice Function to return the specific sales details for a given address /// @param minter address for minter to return mint information for function mintedPerAddress(address minter) external view returns (AddressMintDetails memory); /// @notice This is the opensea/public owner setting that can be set by the contract admin function owner() external view returns (address); /// @notice Admin function to update the public sale configuration settings /// @param newConfig updated public stage config function setPublicSaleConfiguration(PublicSaleConfiguration memory newConfig) external; /// @notice Admin function to update the presale configuration settings /// @param newConfig new presale configuration function setPresaleConfiguration(PresaleConfiguration[] calldata newConfig) external; /// @notice Admin function to reduce collection size (cut suppy) /// @param _newCollectionSize new collection size function reduceSupply(uint64 _newCollectionSize) external; /// @dev Reveal collection artworks /// @param collectionURI collection artwork URI /// @param extension collection artwork URI extension function revealCollection(string memory collectionURI, string memory extension) external; /// @notice Update the metadata renderer /// @param newRenderer new address for renderer /// @param metadataBase data to call to bootstrap data for the new renderer (optional) /// @param dynamicMetadataInfo data to call to bootstrap dynamic metadata for the new renderer (optional) function setMetadataRenderer(address newRenderer, bytes memory metadataBase, bytes memory dynamicMetadataInfo) external; /// @notice This is an admin mint function to mint a quantity to a specific address /// @param to address to mint to /// @param quantity quantity to mint /// @return the id of the first minted NFT function adminMint(address to, uint256 quantity) external returns (uint256); /// @notice This is an admin mint function to mint a single nft each to a list of addresses /// @param to list of addresses to mint an NFT each to /// @return the id of the first minted NFT function adminMintAirdrop(address[] memory to) external returns (uint256); /// @dev Getter for admin role associated with the contract to handle metadata /// @return boolean if address is admin function isAdmin(address user) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721Upgradeable is IERC165Upgradeable { /** * @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 // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (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. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (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. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (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 product uint256 prod1; // Most significant 256 bits of the product assembly { 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) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (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). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // 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. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (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. */ function log2(uint256 value) internal pure returns (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. */ function log2(uint256 value, Rounding rounding) internal pure returns (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. */ function log10(uint256 value) internal pure returns (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. */ function log10(uint256 value, Rounding rounding) internal pure returns (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. */ function log256(uint256 value) internal pure returns (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 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// 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 IERC165Upgradeable { /** * @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); }
{ "remappings": [ "solady/=lib/solady/", "solemate/=/lib/solemate/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "forge-std/=lib/forge-std/src/", "erc721a/contracts/=lib/ERC721A/contracts/", "erc721a-upgradeable/contracts/=lib/ERC721A-Upgradeable/contracts/", "@limitbreak/creator-token-standards/src/=lib/creator-token-standards/src/", "@limitbreak/permit-c/=lib/creator-token-standards/lib/PermitC/src/", "@opensea/tstorish/=lib/creator-token-standards/lib/tstorish/src/", "@openzeppelin/=lib/creator-token-standards/lib/openzeppelin-contracts/", "@rari-capital/solmate/=lib/creator-token-standards/lib/PermitC/lib/solmate/", "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "ERC721A/=lib/creator-token-standards/lib/ERC721A/contracts/", "PermitC/=lib/creator-token-standards/lib/PermitC/", "creator-token-standards/=lib/creator-token-standards/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/creator-token-standards/lib/PermitC/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a/=lib/creator-token-standards/lib/ERC721A/", "forge-gas-metering/=lib/creator-token-standards/lib/PermitC/lib/forge-gas-metering/", "murky/=lib/creator-token-standards/lib/murky/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/creator-token-standards/lib/PermitC/lib/openzeppelin-contracts/contracts/", "solmate/=lib/solmate/src/", "tstorish/=lib/creator-token-standards/lib/tstorish/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"Access_OnlyAdmin","type":"error"},{"inputs":[],"name":"MetadataFrozen","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"string","name":"imageURI","type":"string"},{"indexed":false,"internalType":"string","name":"animationURI","type":"string"}],"name":"DynamicMetadataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"string","name":"metadataBase","type":"string"},{"indexed":false,"internalType":"string","name":"metadataExtension","type":"string"},{"indexed":false,"internalType":"string","name":"contractURI","type":"string"},{"indexed":false,"internalType":"uint256","name":"freezeAt","type":"uint256"}],"name":"MetadataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes32","name":"provenanceHash","type":"bytes32"}],"name":"ProvenanceHashUpdated","type":"event"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dynamicMetadataInfoByContract","outputs":[{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"imageURI","type":"string"},{"internalType":"string","name":"animationURI","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"dynamicTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"metadataBase","type":"bytes"},{"internalType":"bytes","name":"dynamicTokenData","type":"bytes"}],"name":"initializeWithData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"metadataBaseByContract","outputs":[{"internalType":"string","name":"base","type":"string"},{"internalType":"string","name":"extension","type":"string"},{"internalType":"string","name":"contractURI","type":"string"},{"internalType":"uint256","name":"freezeAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"provenanceHashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"revealed","type":"bool"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"imageURI","type":"string"},{"internalType":"string","name":"animationURI","type":"string"}],"name":"updateDynamicMetadataInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"metadataBaseURI","type":"string"},{"internalType":"string","name":"newContractURI","type":"string"}],"name":"updateMetadataBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"metadataBase","type":"string"},{"internalType":"string","name":"metadataExtension","type":"string"},{"internalType":"string","name":"newContractURI","type":"string"},{"internalType":"uint256","name":"freezeAt","type":"uint256"}],"name":"updateMetadataBaseWithDetails","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes32","name":"provenanceHash","type":"bytes32"}],"name":"updateProvenanceHash","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60808060405234601557612077908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630bafbe0814611198578063301a32601461116c57806342495a9514610cf45780636bbde001146107b757806391074f9814610754578063af806d56146102be578063cc1306db146101d3578063d644beac1461014a578063de5af49b14610112578063e8a3d485146100cd5763ea58a14d14610092575f80fd5b346100c95760203660031901126100c9576100c56100b160043561163b565b604051918291602083526020830190611366565b0390f35b5f80fd5b346100c9575f3660031901126100c957335f525f6020526100f3600260405f20016113c2565b8051156100c9576100c590604051918291602083526020830190611366565b346100c95760203660031901126100c9576001600160a01b0361013361127d565b165f526002602052602060405f2054604051908152f35b346100c95760203660031901126100c9576001600160a01b0361016b61127d565b165f5260016020526101b760405f206100c5610186826113c2565b916101c56101a2600261019b600185016113c2565b93016113c2565b91604051958695606087526060870190611366565b908582036020870152611366565b908382036040850152611366565b346100c95760403660031901126100c9576101ec61127d565b6001600160a01b03166024353382141580610252575b6102405760207ff2e078c4022bfd6c56addd06540a4a5dd4252b6b2c424b6840c184063f48fc2791835f52600282528060405f2055604051908152a2005b6040516302bd6bd160e01b8152600490fd5b50604051630935e01b60e21b8152336004820152602081602481865afa9081156102b3575f91610284575b5015610202565b6102a6915060203d6020116102ac575b61029e81836112e4565b8101906114c2565b8361027d565b503d610294565b6040513d5f823e3d90fd5b346100c95760603660031901126100c9576102d761127d565b6001600160401b036024358181116100c9576102f7903690600401611320565b906044358181116100c957610310903690600401611320565b926001600160a01b0316913383141580610703575b6102405760405191610336836112c9565b5f8352835f5260205f81526003908160405f20015480151590816106f8575b506106e6576040519261036784611293565b84845281840190868252604085019189835260608601935f8552895f525f815260405f20965190815184811161056257806103a28a5461138a565b93601f9485811161069a575b508390858311600114610638575f9261062d575b50508160011b915f19908a1b1c19161788555b60019283890190518051908682116105625781906103f3845461138a565b8681116105df575b508490868311600114610581575f92610576575b50505f19828b1b1c191690851b1790555b6002880194519081519485116105625761043a865461138a565b83811161051f575b50809285116001146104a3575092805f805160206120228339815191529b9c97959381936104939a98965f94610498575b50501b915f1990861b1c19161790555b5191015560405193849384611464565b0390a2005b015192508e80610473565b9190601f949394198416865f52835f20935f905b828210610508575050916104939997959391855f805160206120228339815191529e9f9a989694106104f1575b505050811b019055610483565b01515f1983881b60f8161c191690558c80806104e4565b8088869782949787015181550196019401906104b7565b865f52815f208480880160051c820192848910610559575b0160051c019085905b82811061054e575050610442565b5f8155018590610540565b92508192610537565b634e487b7160e01b5f52604160045260245ffd5b015190508f8061040f565b90879350601f19831691855f52865f20925f5b888282106105c957505084116105b2575b505050811b019055610420565b01515f19838d1b60f8161c191690558f80806105a5565b8385015186558b97909501949384019301610594565b909150835f52845f208680850160051c820192878610610624575b918991869594930160051c01915b8281106106165750506103fb565b5f8155859450899101610608565b925081926105fa565b015190508e806103c2565b5f8c81528581209350601f198516905b8682821061068457505090846001959493921061066d575b505050811b0188556103d5565b01515f19838c1b60f8161c191690558e8080610660565b6001859682939686015181550195019301610648565b9091508a5f52835f208580850160051c8201928686106106dd575b9085949392910160051c01905b8181106106cf57506103ae565b5f81558493506001016106c2565b925081926106b5565b60405163777821ff60e11b8152600490fd5b905042101588610355565b50604051630935e01b60e21b8152336004820152602081602481875afa9081156102b3575f91610735575b5015610325565b61074e915060203d6020116102ac5761029e81836112e4565b8561072e565b346100c95760203660031901126100c9576001600160a01b0361077561127d565b165f525f60205260405f20610789816113c2565b6100c5610798600184016113c2565b9260036107a7600283016113c2565b91015490604051948594856114a4565b346100c95760403660031901126100c9576004356001600160401b0381116100c9576107e7903690600401611320565b6024356001600160401b0381116100c957610806903690600401611320565b81518061089e575b50809150518061081a57005b8101606082602083019203126100c95760208201516001600160401b0381116100c95781602061084c928501016115f5565b9060408301516001600160401b0381116100c95781602061086f928601016115f5565b906060840151906001600160401b0382116100c95760206108959261089c9601016115f5565b913361188f565b005b820191604081602085019403126100c95760208101516001600160401b0381116100c9578360206108d1928401016115f5565b926040820151916001600160401b0383116100c9576108f392016020016115f5565b9160405192610901846112c9565b5f8452335f525f602052600360405f2001548015159081610ce9575b506106e6576040519361092f85611293565b8285528060208601528160408601525f6060860152335f525f60205260405f2085518051906001600160401b03821161056257819061096e845461138a565b601f8111610c99575b50602090601f8311600114610c31575f92610c26575b50508160011b915f199060031b1c19161781555b60208601518051906001600160401b0382116105625781906109c6600185015461138a565b601f8111610bd3575b50602090601f8311600114610b65575f92610b5a575b50508160011b915f199060031b1c19161760018201555b60408601519586516001600160401b03811161056257610a1f600284015461138a565b601f8111610b16575b506020601f8211600114610a975791816060926003945f80516020612022833981519152999a9b5f92610a8c575b50508160011b915f1990861b1c19161760028501555b0151910155610a82604051928392339684611464565b0390a2808261080e565b015190508b80610a56565b600284015f5260205f20985f5b601f1984168110610afe5750825f8051602061202283398151915298999a60039593600193606096601f19811610610ae7575b505050811b016002850155610a6c565b01515f1983881b60f8161c191690558b8080610ad7565b828201518b556001909a019960209283019201610aa4565b600284015f5260205f20601f830160051c810160208410610b53575b601f830160051c82018110610b48575050610a28565b5f8155600101610b32565b5080610b32565b0151905088806109e5565b9250600184015f5260205f20905f935b601f1984168510610bb8576001945083601f19811610610ba0575b505050811b0160018201556109fc565b01515f1960f88460031b161c19169055888080610b90565b81810151835560209485019460019093019290910190610b75565b909150600184015f5260205f20601f840160051c81019160208510610c1c575b90601f859493920160051c01905b818110610c0e57506109cf565b5f8155849350600101610c01565b9091508190610bf3565b01519050888061098d565b9250835f5260205f20905f935b601f1984168510610c7e576001945083601f19811610610c66575b505050811b0181556109a1565b01515f1960f88460031b161c19169055888080610c59565b81810151835560209485019460019093019290910190610c3e565b909150835f5260205f20601f840160051c81019160208510610cdf575b90601f859493920160051c01905b818110610cd15750610977565b5f8155849350600101610cc4565b9091508190610cb6565b90504210158561091d565b346100c95760a03660031901126100c957610d0d61127d565b6001600160401b036024358181116100c957610d2d903690600401611320565b6044358281116100c957610d45903690600401611320565b906064358381116100c957610d5e903690600401611320565b608435946001600160a01b031693338514158061111b575b61024057845f5260205f81526003908160405f2001548015159081611110575b506106e65760405192610da884611293565b85845281840190878252604085019186835260608601938b85528a5f525f815260405f2096519081518481116105625780610de38a5461138a565b93601f948581116110c4575b508390858311600114611062575f92611057575b50508160011b915f19908a1b1c19161788555b6001928389019051805190868211610562578190610e34845461138a565b868111611009575b508490868311600114610fab575f92610fa0575b50505f19828b1b1c191690851b1790555b60028801945190815194851161056257610e7b865461138a565b838111610f5d575b5080928511600114610ee0575092806104939997959381935f805160206120228339815191529e9f9a98965f94610ed5575b50501b915f1990861b1c19161790555b51910155604051948594856114a4565b015192508f80610eb5565b9190601f949394198416865f52835f20935f905b828210610f46575050915f805160206120228339815191529d9e9997959391856104939c9a98969410610f2f575b505050811b019055610ec5565b01515f1983881b60f8161c191690558d8080610f22565b808886978294978701518155019601940190610ef4565b865f52815f208480880160051c820192848910610f97575b0160051c019085905b828110610f8c575050610e83565b5f8155018590610f7e565b92508192610f75565b015190505f80610e50565b90879350601f19831691855f52865f20925f5b88828210610ff35750508411610fdc575b505050811b019055610e61565b01515f19838d1b60f8161c191690555f8080610fcf565b8385015186558b97909501949384019301610fbe565b909150835f52845f208680850160051c82019287861061104e575b918991869594930160051c01915b828110611040575050610e3c565b5f8155859450899101611032565b92508192611024565b015190508f80610e03565b5f8c81528581209350601f198516905b868282106110ae575050908460019594939210611097575b505050811b018855610e16565b01515f19838c1b60f8161c191690558f808061108a565b6001859682939686015181550195019301611072565b9091508a5f52835f208580850160051c820192868610611107575b9085949392910160051c01905b8181106110f95750610def565b5f81558493506001016110ec565b925081926110df565b905042101589610d96565b50604051630935e01b60e21b8152336004820152602081602481895afa9081156102b3575f9161114d575b5015610d76565b611166915060203d6020116102ac5761029e81836112e4565b87611146565b346100c95760403660031901126100c95760243580151581036100c9576100b16100c5916004356114da565b346100c95760803660031901126100c9576111b161127d565b6001600160401b036024358181116100c9576111d1903690600401611320565b906044358181116100c9576111ea903690600401611320565b906064359081116100c957611203903690600401611320565b916001600160a01b038416338114159081611227575b506102405761089c9361188f565b604051630935e01b60e21b81523360048201529150602090829060249082905afa9081156102b3575f9161125e575b501585611219565b611277915060203d6020116102ac5761029e81836112e4565b85611256565b600435906001600160a01b03821682036100c957565b608081019081106001600160401b0382111761056257604052565b606081019081106001600160401b0382111761056257604052565b602081019081106001600160401b0382111761056257604052565b90601f801991011681019081106001600160401b0382111761056257604052565b6001600160401b03811161056257601f01601f191660200190565b81601f820112156100c95780359061133782611305565b9261134560405194856112e4565b828452602083830101116100c957815f926020809301838601378301015290565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c921680156113b8575b60208310146113a457565b634e487b7160e01b5f52602260045260245ffd5b91607f1691611399565b9060405191825f82546113d48161138a565b908184526020946001916001811690815f146114425750600114611404575b505050611402925003836112e4565b565b5f90815285812095935091905b81831061142a57505061140293508201015f80806113f3565b85548884018501529485019487945091830191611411565b9250505061140294925060ff191682840152151560051b8201015f80806113f3565b939261149f906114915f9461148360609560808a5260808a0190611366565b9088820360208a0152611366565b908682036040880152611366565b930152565b94939261149160609361148361149f9460808a5260808a0190611366565b908160209103126100c9575180151581036100c95790565b90156115ec57335f526020905f825260405f20906040516114fa81611293565b611503836113c2565b81526001906003611516600186016113c2565b94868301958652611529600282016113c2565b60408401520154606082015251908151156100c95791849261154a82611cab565b9181602161155a60018601611c79565b94850101905b6115b6575b5050508290816115b39551916040519785899651918291018488015e8501908282015f8152815193849201905e01908282015f8152815193849201905e015f838201520380845201826112e4565b90565b5f190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115e757919082611560565b611565565b6115b39061163b565b81601f820112156100c95780519061160c82611305565b9261161a60405194856112e4565b828452602083830101116100c957815f9260208093018386015e8301015290565b335f5260019060209160018352604090815f209282519161165b836112ae565b611664856113c2565b83526116846002611677600188016113c2565b96888601978852016113c2565b84840190808252865151159081611885575b506100c95784516306fdde0360e01b8152935f85600481335afa94851561187b57908895949392915f95611832575b5051965190519192916116d791611d85565b916116e182611cab565b918160216116f160018601611c79565b94850101905b6117fc575b50505060446117b393856115b3988195828a996117ae97603d9c51998a97693d913730b6b2911d101160b11b828a0152805191829101602a8a015e87019061202360f01b602a830152805192839101602c83015e01631116101160e11b9384602c8301526e3232b9b1b934b83a34b7b7111d101160891b6030830152805192839101603f83015e0191603f830152805192839101604383015e01607d60f81b60438201520360248101845201826112e4565b611ec5565b90519384917f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000828401528051918291018484015e81015f8382015203601d8101845201826112e4565b5f190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561182d579190826116f7565b6116fc565b91955093503d805f833e61184681836112e4565b81019488828703126100c9578151916001600160401b0383116100c95789966116d79361187392016115f5565b9490916116c5565b86513d5f823e3d90fd5b905051155f611696565b906040519061189d826112ae565b81526020810183815284604083015260018060a01b0383165f52600160205260405f209082518051906001600160401b0382116105625781906118e0855461138a565b601f8111611c29575b50602090601f8311600114611bc5575f92611bba575b50508160011b915f199060031b1c19161782555b51805160018301916001600160401b03821161056257611933835461138a565b601f8111611b75575b50602090601f8311600114611b0b57918060029492604096945f92611b00575b50508160011b915f199060031b1c19161790555b019101518051906001600160401b0382116105625761198f835461138a565b601f8111611abb575b50602090601f8311600114611a2d579282611a1d93611a0496937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098965f92611a22575b50508160011b915f199060031b1c19161790555b604051938493604085526040850190611366565b83810360208501526001600160a01b0390911695611366565b0390a2565b015190505f806119dc565b90601f19831691845f5260205f20925f5b818110611aa3575093611a0496937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098969360019383611a1d9810611a8b575b505050811b0190556119f0565b01515f1960f88460031b161c191690555f8080611a7e565b92936020600181928786015181550195019301611a3e565b835f5260205f20601f840160051c81019160208510611af6575b601f0160051c01905b818110611aeb5750611998565b5f8155600101611ade565b9091508190611ad5565b015190505f8061195c565b90601f19831691845f5260205f20925f5b818110611b5d5750926001928592604098966002989610611b45575b505050811b019055611970565b01515f1960f88460031b161c191690555f8080611b38565b92936020600181928786015181550195019301611b1c565b835f5260205f20601f840160051c81019160208510611bb0575b601f0160051c01905b818110611ba5575061193c565b5f8155600101611b98565b9091508190611b8f565b015190505f806118ff565b5f868152602081209350601f198516905b818110611c115750908460019594939210611bf9575b505050811b018255611913565b01515f1960f88460031b161c191690555f8080611bec565b92936020600181928786015181550195019301611bd6565b909150845f5260205f20601f840160051c81019160208510611c6f575b90601f859493920160051c01905b818110611c6157506118e9565b5f8155849350600101611c54565b9091508190611c46565b90611c8382611305565b611c9060405191826112e4565b8281528092611ca1601f1991611305565b0190602036910137565b5f907a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000080821015611d78575b50600a906d04ee2d6d415b85acef810000000080821015611d6b575b50662386f26fc1000080821015611d5e575b506305f5e10080821015611d51575b5061271080821015611d44575b506064811015611d36575b1015611d305790565b60010190565b606460029104920191611d27565b600491049201915f611d1c565b600891049201915f611d0f565b601091049201915f611d00565b602091049201915f611cee565b604092509004600a611cd2565b805115159082511515918080611ebe575b611e4a57611e025750611db65750604051611db0816112c9565b5f815290565b6115b360326020926040519384917030b734b6b0ba34b7b72fbab936111d101160791b82840152805191829101603184015e8101601160f91b60318201520360128101845201826112e4565b602092506115b39150602a906040519384916834b6b0b3b2911d101160b91b82840152805191829101602984015e8101601160f91b602982015203600a8101845201826112e4565b506115b39150603f90602080946040519586936834b6b0b3b2911d101160b91b82860152805191829101602986015e830190741116101130b734b6b0ba34b7b72fbab936111d101160591b6029830152805192839101603e83015e01601160f91b603e82015203601f8101845201826112e4565b5082611d96565b80511561201457604051611ed8816112ae565b604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604082015281519160029260028101809111612000576003908190046001600160fe1b038116810361200057611f5f906002959492951b611c79565b936020850193839284518501935b848110611fad575050505050600390510680600114611f9b57600214611f91575090565b603d905f19015390565b50603d90815f19820153600119015390565b8360049197929394959701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c168801015188850153168501015186820153019593929190611f6d565b634e487b7160e01b5f52601160045260245ffd5b50604051611db0816112c956fe5eff125d5659803f33dbda215d6e8bfe0a404fd213a9ecb5e61973ee16cb17e7a2646970667358221220a44770d6a69e8235dcbfc6961c4e1d883363aaed265dfd299161f3504a7c3e0f64736f6c63430008190033
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80630bafbe0814611198578063301a32601461116c57806342495a9514610cf45780636bbde001146107b757806391074f9814610754578063af806d56146102be578063cc1306db146101d3578063d644beac1461014a578063de5af49b14610112578063e8a3d485146100cd5763ea58a14d14610092575f80fd5b346100c95760203660031901126100c9576100c56100b160043561163b565b604051918291602083526020830190611366565b0390f35b5f80fd5b346100c9575f3660031901126100c957335f525f6020526100f3600260405f20016113c2565b8051156100c9576100c590604051918291602083526020830190611366565b346100c95760203660031901126100c9576001600160a01b0361013361127d565b165f526002602052602060405f2054604051908152f35b346100c95760203660031901126100c9576001600160a01b0361016b61127d565b165f5260016020526101b760405f206100c5610186826113c2565b916101c56101a2600261019b600185016113c2565b93016113c2565b91604051958695606087526060870190611366565b908582036020870152611366565b908382036040850152611366565b346100c95760403660031901126100c9576101ec61127d565b6001600160a01b03166024353382141580610252575b6102405760207ff2e078c4022bfd6c56addd06540a4a5dd4252b6b2c424b6840c184063f48fc2791835f52600282528060405f2055604051908152a2005b6040516302bd6bd160e01b8152600490fd5b50604051630935e01b60e21b8152336004820152602081602481865afa9081156102b3575f91610284575b5015610202565b6102a6915060203d6020116102ac575b61029e81836112e4565b8101906114c2565b8361027d565b503d610294565b6040513d5f823e3d90fd5b346100c95760603660031901126100c9576102d761127d565b6001600160401b036024358181116100c9576102f7903690600401611320565b906044358181116100c957610310903690600401611320565b926001600160a01b0316913383141580610703575b6102405760405191610336836112c9565b5f8352835f5260205f81526003908160405f20015480151590816106f8575b506106e6576040519261036784611293565b84845281840190868252604085019189835260608601935f8552895f525f815260405f20965190815184811161056257806103a28a5461138a565b93601f9485811161069a575b508390858311600114610638575f9261062d575b50508160011b915f19908a1b1c19161788555b60019283890190518051908682116105625781906103f3845461138a565b8681116105df575b508490868311600114610581575f92610576575b50505f19828b1b1c191690851b1790555b6002880194519081519485116105625761043a865461138a565b83811161051f575b50809285116001146104a3575092805f805160206120228339815191529b9c97959381936104939a98965f94610498575b50501b915f1990861b1c19161790555b5191015560405193849384611464565b0390a2005b015192508e80610473565b9190601f949394198416865f52835f20935f905b828210610508575050916104939997959391855f805160206120228339815191529e9f9a989694106104f1575b505050811b019055610483565b01515f1983881b60f8161c191690558c80806104e4565b8088869782949787015181550196019401906104b7565b865f52815f208480880160051c820192848910610559575b0160051c019085905b82811061054e575050610442565b5f8155018590610540565b92508192610537565b634e487b7160e01b5f52604160045260245ffd5b015190508f8061040f565b90879350601f19831691855f52865f20925f5b888282106105c957505084116105b2575b505050811b019055610420565b01515f19838d1b60f8161c191690558f80806105a5565b8385015186558b97909501949384019301610594565b909150835f52845f208680850160051c820192878610610624575b918991869594930160051c01915b8281106106165750506103fb565b5f8155859450899101610608565b925081926105fa565b015190508e806103c2565b5f8c81528581209350601f198516905b8682821061068457505090846001959493921061066d575b505050811b0188556103d5565b01515f19838c1b60f8161c191690558e8080610660565b6001859682939686015181550195019301610648565b9091508a5f52835f208580850160051c8201928686106106dd575b9085949392910160051c01905b8181106106cf57506103ae565b5f81558493506001016106c2565b925081926106b5565b60405163777821ff60e11b8152600490fd5b905042101588610355565b50604051630935e01b60e21b8152336004820152602081602481875afa9081156102b3575f91610735575b5015610325565b61074e915060203d6020116102ac5761029e81836112e4565b8561072e565b346100c95760203660031901126100c9576001600160a01b0361077561127d565b165f525f60205260405f20610789816113c2565b6100c5610798600184016113c2565b9260036107a7600283016113c2565b91015490604051948594856114a4565b346100c95760403660031901126100c9576004356001600160401b0381116100c9576107e7903690600401611320565b6024356001600160401b0381116100c957610806903690600401611320565b81518061089e575b50809150518061081a57005b8101606082602083019203126100c95760208201516001600160401b0381116100c95781602061084c928501016115f5565b9060408301516001600160401b0381116100c95781602061086f928601016115f5565b906060840151906001600160401b0382116100c95760206108959261089c9601016115f5565b913361188f565b005b820191604081602085019403126100c95760208101516001600160401b0381116100c9578360206108d1928401016115f5565b926040820151916001600160401b0383116100c9576108f392016020016115f5565b9160405192610901846112c9565b5f8452335f525f602052600360405f2001548015159081610ce9575b506106e6576040519361092f85611293565b8285528060208601528160408601525f6060860152335f525f60205260405f2085518051906001600160401b03821161056257819061096e845461138a565b601f8111610c99575b50602090601f8311600114610c31575f92610c26575b50508160011b915f199060031b1c19161781555b60208601518051906001600160401b0382116105625781906109c6600185015461138a565b601f8111610bd3575b50602090601f8311600114610b65575f92610b5a575b50508160011b915f199060031b1c19161760018201555b60408601519586516001600160401b03811161056257610a1f600284015461138a565b601f8111610b16575b506020601f8211600114610a975791816060926003945f80516020612022833981519152999a9b5f92610a8c575b50508160011b915f1990861b1c19161760028501555b0151910155610a82604051928392339684611464565b0390a2808261080e565b015190508b80610a56565b600284015f5260205f20985f5b601f1984168110610afe5750825f8051602061202283398151915298999a60039593600193606096601f19811610610ae7575b505050811b016002850155610a6c565b01515f1983881b60f8161c191690558b8080610ad7565b828201518b556001909a019960209283019201610aa4565b600284015f5260205f20601f830160051c810160208410610b53575b601f830160051c82018110610b48575050610a28565b5f8155600101610b32565b5080610b32565b0151905088806109e5565b9250600184015f5260205f20905f935b601f1984168510610bb8576001945083601f19811610610ba0575b505050811b0160018201556109fc565b01515f1960f88460031b161c19169055888080610b90565b81810151835560209485019460019093019290910190610b75565b909150600184015f5260205f20601f840160051c81019160208510610c1c575b90601f859493920160051c01905b818110610c0e57506109cf565b5f8155849350600101610c01565b9091508190610bf3565b01519050888061098d565b9250835f5260205f20905f935b601f1984168510610c7e576001945083601f19811610610c66575b505050811b0181556109a1565b01515f1960f88460031b161c19169055888080610c59565b81810151835560209485019460019093019290910190610c3e565b909150835f5260205f20601f840160051c81019160208510610cdf575b90601f859493920160051c01905b818110610cd15750610977565b5f8155849350600101610cc4565b9091508190610cb6565b90504210158561091d565b346100c95760a03660031901126100c957610d0d61127d565b6001600160401b036024358181116100c957610d2d903690600401611320565b6044358281116100c957610d45903690600401611320565b906064358381116100c957610d5e903690600401611320565b608435946001600160a01b031693338514158061111b575b61024057845f5260205f81526003908160405f2001548015159081611110575b506106e65760405192610da884611293565b85845281840190878252604085019186835260608601938b85528a5f525f815260405f2096519081518481116105625780610de38a5461138a565b93601f948581116110c4575b508390858311600114611062575f92611057575b50508160011b915f19908a1b1c19161788555b6001928389019051805190868211610562578190610e34845461138a565b868111611009575b508490868311600114610fab575f92610fa0575b50505f19828b1b1c191690851b1790555b60028801945190815194851161056257610e7b865461138a565b838111610f5d575b5080928511600114610ee0575092806104939997959381935f805160206120228339815191529e9f9a98965f94610ed5575b50501b915f1990861b1c19161790555b51910155604051948594856114a4565b015192508f80610eb5565b9190601f949394198416865f52835f20935f905b828210610f46575050915f805160206120228339815191529d9e9997959391856104939c9a98969410610f2f575b505050811b019055610ec5565b01515f1983881b60f8161c191690558d8080610f22565b808886978294978701518155019601940190610ef4565b865f52815f208480880160051c820192848910610f97575b0160051c019085905b828110610f8c575050610e83565b5f8155018590610f7e565b92508192610f75565b015190505f80610e50565b90879350601f19831691855f52865f20925f5b88828210610ff35750508411610fdc575b505050811b019055610e61565b01515f19838d1b60f8161c191690555f8080610fcf565b8385015186558b97909501949384019301610fbe565b909150835f52845f208680850160051c82019287861061104e575b918991869594930160051c01915b828110611040575050610e3c565b5f8155859450899101611032565b92508192611024565b015190508f80610e03565b5f8c81528581209350601f198516905b868282106110ae575050908460019594939210611097575b505050811b018855610e16565b01515f19838c1b60f8161c191690558f808061108a565b6001859682939686015181550195019301611072565b9091508a5f52835f208580850160051c820192868610611107575b9085949392910160051c01905b8181106110f95750610def565b5f81558493506001016110ec565b925081926110df565b905042101589610d96565b50604051630935e01b60e21b8152336004820152602081602481895afa9081156102b3575f9161114d575b5015610d76565b611166915060203d6020116102ac5761029e81836112e4565b87611146565b346100c95760403660031901126100c95760243580151581036100c9576100b16100c5916004356114da565b346100c95760803660031901126100c9576111b161127d565b6001600160401b036024358181116100c9576111d1903690600401611320565b906044358181116100c9576111ea903690600401611320565b906064359081116100c957611203903690600401611320565b916001600160a01b038416338114159081611227575b506102405761089c9361188f565b604051630935e01b60e21b81523360048201529150602090829060249082905afa9081156102b3575f9161125e575b501585611219565b611277915060203d6020116102ac5761029e81836112e4565b85611256565b600435906001600160a01b03821682036100c957565b608081019081106001600160401b0382111761056257604052565b606081019081106001600160401b0382111761056257604052565b602081019081106001600160401b0382111761056257604052565b90601f801991011681019081106001600160401b0382111761056257604052565b6001600160401b03811161056257601f01601f191660200190565b81601f820112156100c95780359061133782611305565b9261134560405194856112e4565b828452602083830101116100c957815f926020809301838601378301015290565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c921680156113b8575b60208310146113a457565b634e487b7160e01b5f52602260045260245ffd5b91607f1691611399565b9060405191825f82546113d48161138a565b908184526020946001916001811690815f146114425750600114611404575b505050611402925003836112e4565b565b5f90815285812095935091905b81831061142a57505061140293508201015f80806113f3565b85548884018501529485019487945091830191611411565b9250505061140294925060ff191682840152151560051b8201015f80806113f3565b939261149f906114915f9461148360609560808a5260808a0190611366565b9088820360208a0152611366565b908682036040880152611366565b930152565b94939261149160609361148361149f9460808a5260808a0190611366565b908160209103126100c9575180151581036100c95790565b90156115ec57335f526020905f825260405f20906040516114fa81611293565b611503836113c2565b81526001906003611516600186016113c2565b94868301958652611529600282016113c2565b60408401520154606082015251908151156100c95791849261154a82611cab565b9181602161155a60018601611c79565b94850101905b6115b6575b5050508290816115b39551916040519785899651918291018488015e8501908282015f8152815193849201905e01908282015f8152815193849201905e015f838201520380845201826112e4565b90565b5f190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115e757919082611560565b611565565b6115b39061163b565b81601f820112156100c95780519061160c82611305565b9261161a60405194856112e4565b828452602083830101116100c957815f9260208093018386015e8301015290565b335f5260019060209160018352604090815f209282519161165b836112ae565b611664856113c2565b83526116846002611677600188016113c2565b96888601978852016113c2565b84840190808252865151159081611885575b506100c95784516306fdde0360e01b8152935f85600481335afa94851561187b57908895949392915f95611832575b5051965190519192916116d791611d85565b916116e182611cab565b918160216116f160018601611c79565b94850101905b6117fc575b50505060446117b393856115b3988195828a996117ae97603d9c51998a97693d913730b6b2911d101160b11b828a0152805191829101602a8a015e87019061202360f01b602a830152805192839101602c83015e01631116101160e11b9384602c8301526e3232b9b1b934b83a34b7b7111d101160891b6030830152805192839101603f83015e0191603f830152805192839101604383015e01607d60f81b60438201520360248101845201826112e4565b611ec5565b90519384917f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000828401528051918291018484015e81015f8382015203601d8101845201826112e4565b5f190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561182d579190826116f7565b6116fc565b91955093503d805f833e61184681836112e4565b81019488828703126100c9578151916001600160401b0383116100c95789966116d79361187392016115f5565b9490916116c5565b86513d5f823e3d90fd5b905051155f611696565b906040519061189d826112ae565b81526020810183815284604083015260018060a01b0383165f52600160205260405f209082518051906001600160401b0382116105625781906118e0855461138a565b601f8111611c29575b50602090601f8311600114611bc5575f92611bba575b50508160011b915f199060031b1c19161782555b51805160018301916001600160401b03821161056257611933835461138a565b601f8111611b75575b50602090601f8311600114611b0b57918060029492604096945f92611b00575b50508160011b915f199060031b1c19161790555b019101518051906001600160401b0382116105625761198f835461138a565b601f8111611abb575b50602090601f8311600114611a2d579282611a1d93611a0496937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098965f92611a22575b50508160011b915f199060031b1c19161790555b604051938493604085526040850190611366565b83810360208501526001600160a01b0390911695611366565b0390a2565b015190505f806119dc565b90601f19831691845f5260205f20925f5b818110611aa3575093611a0496937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098969360019383611a1d9810611a8b575b505050811b0190556119f0565b01515f1960f88460031b161c191690555f8080611a7e565b92936020600181928786015181550195019301611a3e565b835f5260205f20601f840160051c81019160208510611af6575b601f0160051c01905b818110611aeb5750611998565b5f8155600101611ade565b9091508190611ad5565b015190505f8061195c565b90601f19831691845f5260205f20925f5b818110611b5d5750926001928592604098966002989610611b45575b505050811b019055611970565b01515f1960f88460031b161c191690555f8080611b38565b92936020600181928786015181550195019301611b1c565b835f5260205f20601f840160051c81019160208510611bb0575b601f0160051c01905b818110611ba5575061193c565b5f8155600101611b98565b9091508190611b8f565b015190505f806118ff565b5f868152602081209350601f198516905b818110611c115750908460019594939210611bf9575b505050811b018255611913565b01515f1960f88460031b161c191690555f8080611bec565b92936020600181928786015181550195019301611bd6565b909150845f5260205f20601f840160051c81019160208510611c6f575b90601f859493920160051c01905b818110611c6157506118e9565b5f8155849350600101611c54565b9091508190611c46565b90611c8382611305565b611c9060405191826112e4565b8281528092611ca1601f1991611305565b0190602036910137565b5f907a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000080821015611d78575b50600a906d04ee2d6d415b85acef810000000080821015611d6b575b50662386f26fc1000080821015611d5e575b506305f5e10080821015611d51575b5061271080821015611d44575b506064811015611d36575b1015611d305790565b60010190565b606460029104920191611d27565b600491049201915f611d1c565b600891049201915f611d0f565b601091049201915f611d00565b602091049201915f611cee565b604092509004600a611cd2565b805115159082511515918080611ebe575b611e4a57611e025750611db65750604051611db0816112c9565b5f815290565b6115b360326020926040519384917030b734b6b0ba34b7b72fbab936111d101160791b82840152805191829101603184015e8101601160f91b60318201520360128101845201826112e4565b602092506115b39150602a906040519384916834b6b0b3b2911d101160b91b82840152805191829101602984015e8101601160f91b602982015203600a8101845201826112e4565b506115b39150603f90602080946040519586936834b6b0b3b2911d101160b91b82860152805191829101602986015e830190741116101130b734b6b0ba34b7b72fbab936111d101160591b6029830152805192839101603e83015e01601160f91b603e82015203601f8101845201826112e4565b5082611d96565b80511561201457604051611ed8816112ae565b604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604082015281519160029260028101809111612000576003908190046001600160fe1b038116810361200057611f5f906002959492951b611c79565b936020850193839284518501935b848110611fad575050505050600390510680600114611f9b57600214611f91575090565b603d905f19015390565b50603d90815f19820153600119015390565b8360049197929394959701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c168801015188850153168501015186820153019593929190611f6d565b634e487b7160e01b5f52601160045260245ffd5b50604051611db0816112c956fe5eff125d5659803f33dbda215d6e8bfe0a404fd213a9ecb5e61973ee16cb17e7a2646970667358221220a44770d6a69e8235dcbfc6961c4e1d883363aaed265dfd299161f3504a7c3e0f64736f6c63430008190033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.