Overview
APE Balance
0 APE
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 87 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Update Metadata ... | 5109780 | 15 hrs ago | IN | 0 APE | 0.0016771 | ||||
Update Metadata ... | 5101999 | 17 hrs ago | IN | 0 APE | 0.00167713 | ||||
Update Metadata ... | 5089353 | 21 hrs ago | IN | 0 APE | 0.0016771 | ||||
Update Metadata ... | 5076436 | 24 hrs ago | IN | 0 APE | 0.00151502 | ||||
Update Dynamic M... | 5074145 | 25 hrs ago | IN | 0 APE | 0.00145119 | ||||
Update Dynamic M... | 5073703 | 25 hrs ago | IN | 0 APE | 0.0013088 | ||||
Update Metadata ... | 5072299 | 25 hrs ago | IN | 0 APE | 0.0015862 | ||||
Update Metadata ... | 5060261 | 28 hrs ago | IN | 0 APE | 0.00167707 | ||||
Update Metadata ... | 5056575 | 29 hrs ago | IN | 0 APE | 0.00174828 | ||||
Update Metadata ... | 5023161 | 35 hrs ago | IN | 0 APE | 0.0016771 | ||||
Update Metadata ... | 4980971 | 42 hrs ago | IN | 0 APE | 0.00151499 | ||||
Update Metadata ... | 4948356 | 2 days ago | IN | 0 APE | 0.00158617 | ||||
Update Metadata ... | 4938557 | 2 days ago | IN | 0 APE | 0.00158617 | ||||
Update Dynamic M... | 4937805 | 2 days ago | IN | 0 APE | 0.00143998 | ||||
Update Dynamic M... | 4937800 | 2 days ago | IN | 0 APE | 0.00143995 | ||||
Update Dynamic M... | 4904561 | 2 days ago | IN | 0 APE | 0.00172987 | ||||
Update Metadata ... | 4881403 | 2 days ago | IN | 0 APE | 0.00151504 | ||||
Update Metadata ... | 4876370 | 2 days ago | IN | 0 APE | 0.00151502 | ||||
Update Metadata ... | 4863094 | 2 days ago | IN | 0 APE | 0.00167987 | ||||
Update Metadata ... | 4741942 | 3 days ago | IN | 0 APE | 0.00167987 | ||||
Update Metadata ... | 4685385 | 4 days ago | IN | 0 APE | 0.0015862 | ||||
Update Metadata ... | 4655319 | 4 days ago | IN | 0 APE | 0.00158617 | ||||
Update Metadata ... | 4634154 | 5 days ago | IN | 0 APE | 0.00167987 | ||||
Update Metadata ... | 4632099 | 5 days ago | IN | 0 APE | 0.00167987 | ||||
Update Dynamic M... | 4609974 | 5 days ago | IN | 0 APE | 0.00143924 |
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:
paris 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 "../utils/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.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; import "./math/SignedMathUpgradeable.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 `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.abs(value)))); } /** * @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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// 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 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.9.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) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ 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 256, 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 << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMathUpgradeable { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// 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.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.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 `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// 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 invalid collection size when publish error Setup_InvalidCollectionSize(); /// @notice Presale stage out of supported range error Setup_Presale_StageOutOfRange(); /// @notice Royalty percentage too high error Setup_RoyaltyPercentageTooHigh(uint16 maxRoyaltyBPS); /// @notice Unable to finalize an edition not marked as open (size set to uint64_max_value) error Admin_UnableToFinalizeNotOpenEdition(); /// @notice Invalid admin upgrade address error Admin_InvalidUpgradeAddress(address proposedAddress); /// @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 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 event RoyaltyChanged(address indexed changedBy, uint256 newPercentage); /// @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 an open mint is finalized and further minting is closed forever on the contract. /// @param sender address sending close mint /// @param numberOfMints number of mints the contract is finalized at event OpenMintFinalized(address indexed sender, uint256 numberOfMints); /// @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 (uint160) IMetadataRenderer metadataRenderer; /// @dev Max supply of collection (uint160+64 = 224) uint64 collectionSize; /// @dev Royalty amount in bps (uint224+16 = 240) uint16 royaltyBPS; /// @dev Funds recipient for sale (new slot, uint160) address payable fundsRecipient; /// @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; /// @notice Purchase mint limit per address (if set to 0 === unlimited mints) uint32 maxSalePurchasePerAddress; /// @dev uint64 type allows for dates into 292 billion years /// @notice Public sale start timestamp (136+64 = 186) uint64 publicSaleStart; /// @notice Public sale end timestamp (186+64 = 250) uint64 publicSaleEnd; } /// @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[] memory newConfig) external; /// @dev Reveal collection artworks /// @param collectionURI collection artwork URI function revealCollection(string memory collectionURI) 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(IMetadataRenderer 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.9.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.9.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) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ 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 256, 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 << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// 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": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/", "forge-std/=lib/forge-std/src/", "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "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
60808060405234601557612251908161001b8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80630bafbe08146112dc578063301a3260146112b057806342495a9514610da75780636bbde0011461085357806391074f98146107ed578063af806d56146102ce578063cc1306db146101df578063d644beac14610154578063de5af49b1461011a578063e8a3d485146100d15763ea58a14d1461009557600080fd5b346100cc5760203660031901126100cc576100c86100b46004356117b2565b6040519182916020835260208301906114cf565b0390f35b600080fd5b346100cc5760003660031901126100cc573360005260006020526100fb600260406000200161152e565b8051156100cc576100c8906040519182916020835260208301906114cf565b346100cc5760203660031901126100cc576001600160a01b0361013b6113c2565b1660005260026020526020604060002054604051908152f35b346100cc5760203660031901126100cc576001600160a01b036101756113c2565b1660005260016020526101c360406000206100c86101928261152e565b916101d16101ae60026101a76001850161152e565b930161152e565b916040519586956060875260608701906114cf565b9085820360208701526114cf565b9083820360408501526114cf565b346100cc5760403660031901126100cc576101f86113c2565b6001600160a01b03166024353382141580610260575b61024e5760207ff2e078c4022bfd6c56addd06540a4a5dd4252b6b2c424b6840c184063f48fc2791836000526002825280604060002055604051908152a2005b6040516302bd6bd160e01b8152600490fd5b50604051630935e01b60e21b8152336004820152602081602481865afa9081156102c257600091610293575b501561020e565b6102b5915060203d6020116102bb575b6102ad8183611429565b810190611632565b8361028c565b503d6102a3565b6040513d6000823e3d90fd5b346100cc5760603660031901126100cc576102e76113c2565b6024356001600160401b0381116100cc57610306903690600401611465565b6044356001600160401b0381116100cc57610325903690600401611465565b916001600160a01b03811633141580610792575b61024e576040519061034a8261140e565b60008083526001600160a01b0382168152602081905260409020600301548015159081610787575b506107755760405193610384856113d8565b8385528260208601528060408601526000606086015260018060a01b0382166000526000602052604060002085518051906001600160401b0382116105d35781906103cf84546114f4565b601f8111610725575b50602090601f83116001146106bf576000926106b4575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d357819061042960018501546114f4565b601f8111610661575b50602090601f83116001146105f4576000926105e9575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d35761048460028401546114f4565b601f811161058c575b506020601f8211600114610506576104f6949392826003936060936000805160206121fc8339815191529b9c6000926104fb575b50508160011b9160001990861b1c19161760028501555b01519101556040516001600160a01b039093169592938493846115d3565b0390a2005b015190508c806104c1565b601f198216986002850160005260206000209960005b8181106105745750836000805160206121fc8339815191529a9b6060946104f6999897946003976001951061055c575b505050811b0160028501556104d8565b015160001983881b60f8161c191690558c808061054c565b838301518c556001909b019a6020938401930161051c565b600284016000526020600020601f830160051c8101602084106105cc575b601f830160051c820181106105c057505061048d565b600081556001016105aa565b50806105aa565b634e487b7160e01b600052604160045260246000fd5b015190508880610449565b600185016000908152602081209350601f198516905b8181106106495750908460019594939210610630575b505050811b016001820155610461565b015160001960f88460031b161c19169055888080610620565b9293602060018192878601518155019501930161060a565b909150600184016000526020600020601f840160051c8101602085106106ad575b90849392915b601f830160051c8201811061069e575050610432565b60008155859450600101610688565b5080610682565b0151905088806103ef565b6000858152602081209350601f198516905b81811061070d57509084600195949392106106f4575b505050811b018155610404565b015160001960f88460031b161c191690558880806106e7565b929360206001819287860151815501950193016106d1565b909150836000526020600020601f840160051c81016020851061076e575b90849392915b601f830160051c8201811061075f5750506103d8565b60008155859450600101610749565b5080610743565b60405163777821ff60e11b8152600490fd5b905042101585610372565b50604051630935e01b60e21b81523360048201526020816024816001600160a01b0386165afa9081156102c2576000916107ce575b5015610339565b6107e7915060203d6020116102bb576102ad8183611429565b846107c7565b346100cc5760203660031901126100cc576001600160a01b0361080e6113c2565b16600052600060205260406000206108258161152e565b6100c86108346001840161152e565b9260036108436002830161152e565b9101549060405194859485611614565b346100cc5760403660031901126100cc576004356001600160401b0381116100cc57610883903690600401611465565b6024356001600160401b0381116100cc576108a2903690600401611465565b81518061093a575b5080915051806108b657005b8101606082602083019203126100cc5760208201516001600160401b0381116100cc578160206108e892850101611770565b9060408301516001600160401b0381116100cc5781602061090b92860101611770565b906060840151906001600160401b0382116100cc57602061093192610938960101611770565b9133611a2b565b005b820191604081602085019403126100cc5760208101516001600160401b0381116100cc5783602061096d92840101611770565b926040820151916001600160401b0383116100cc5761098f9201602001611770565b916040519261099d8461140e565b600084523360005260006020526003604060002001548015159081610d9c575b5061077557604051936109cf856113d8565b82855280602086015281604086015260006060860152336000526000602052604060002085518051906001600160401b0382116105d3578190610a1284546114f4565b601f8111610d4c575b50602090601f8311600114610ce657600092610cdb575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d3578190610a6c60018501546114f4565b601f8111610c88575b50602090601f8311600114610c1657600092610c0b575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d357610ac760028401546114f4565b601f8111610bc4575b506020601f8211600114610b425791816060926003946000805160206121fc833981519152999a9b600092610b37575b50508160011b9160001990861b1c19161760028501555b0151910155610b2d6040519283923396846115d3565b0390a280826108aa565b015190508b80610b00565b601f198216986002850160005260206000209960005b818110610bac5750926000805160206121fc83398151915298999a600395936001938360609710610b94575b505050811b016002850155610b17565b015160001983881b60f8161c191690558b8080610b84565b838301518c556001909b019a60209384019301610b58565b600284016000526020600020601f830160051c810160208410610c04575b601f830160051c82018110610bf8575050610ad0565b60008155600101610be2565b5080610be2565b015190508880610a8c565b9250600184016000526020600020906000935b601f1984168510610c6d576001945083601f19811610610c54575b505050811b016001820155610aa4565b015160001960f88460031b161c19169055888080610c44565b81810151835560209485019460019093019290910190610c29565b909150600184016000526020600020601f840160051c810160208510610cd4575b90849392915b601f830160051c82018110610cc5575050610a75565b60008155859450600101610caf565b5080610ca9565b015190508880610a32565b6000858152602081209350601f198516905b818110610d345750908460019594939210610d1b575b505050811b018155610a47565b015160001960f88460031b161c19169055888080610d0e565b92936020600181928786015181550195019301610cf8565b909150836000526020600020601f840160051c810160208510610d95575b90849392915b601f830160051c82018110610d86575050610a1b565b60008155859450600101610d70565b5080610d6a565b9050421015856109bd565b346100cc5760a03660031901126100cc57610dc06113c2565b6024356001600160401b0381116100cc57610ddf903690600401611465565b906044356001600160401b0381116100cc57610dff903690600401611465565b906064356001600160401b0381116100cc57610e1f903690600401611465565b906001600160a01b03811633141580611255575b61024e576001600160a01b038116600090815260208190526040902060030154801515908161124a575b506107755760405193610e6f856113d8565b808552836020860152826040860152608435606086015260018060a01b0382166000526000602052604060002085518051906001600160401b0382116105d3578190610ebb84546114f4565b601f81116111fa575b50602090601f831160011461119457600092611189575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d3578190610f1560018501546114f4565b601f8111611136575b50602090601f83116001146110c9576000926110be575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d357610f7060028401546114f4565b601f8111611077575b506020601f8211600114610ff1576104f6949392826003936060936000805160206121fc8339815191529b9c600092610fe6575b50508160011b9160001990861b1c19161760028501555b01519101556040516001600160a01b0390931695929384936084359285611614565b015190508c80610fad565b601f198216986002850160005260206000209960005b81811061105f5750836000805160206121fc8339815191529a9b6060946104f69998979460039760019510611047575b505050811b016002850155610fc4565b015160001983881b60f8161c191690558c8080611037565b838301518c556001909b019a60209384019301611007565b600284016000526020600020601f830160051c8101602084106110b7575b601f830160051c820181106110ab575050610f79565b60008155600101611095565b5080611095565b015190508880610f35565b600185016000908152602081209350601f198516905b81811061111e5750908460019594939210611105575b505050811b016001820155610f4d565b015160001960f88460031b161c191690558880806110f5565b929360206001819287860151815501950193016110df565b909150600184016000526020600020601f840160051c810160208510611182575b90849392915b601f830160051c82018110611173575050610f1e565b6000815585945060010161115d565b5080611157565b015190508880610edb565b6000858152602081209350601f198516905b8181106111e257509084600195949392106111c9575b505050811b018155610ef0565b015160001960f88460031b161c191690558880806111bc565b929360206001819287860151815501950193016111a6565b909150836000526020600020601f840160051c810160208510611243575b90849392915b601f830160051c82018110611234575050610ec4565b6000815585945060010161121e565b5080611218565b905042101585610e5d565b50604051630935e01b60e21b81523360048201526020816024816001600160a01b0386165afa9081156102c257600091611291575b5015610e33565b6112aa915060203d6020116102bb576102ad8183611429565b8561128a565b346100cc5760403660031901126100cc5760243580151581036100cc576100b46100c89160043561164a565b346100cc5760803660031901126100cc576112f56113c2565b6001600160401b036024358181116100cc57611315903690600401611465565b906044358181116100cc5761132e903690600401611465565b906064359081116100cc57611347903690600401611465565b916001600160a01b03841633811415908161136b575b5061024e5761093893611a2b565b604051630935e01b60e21b81523360048201529150602090829060249082905afa9081156102c2576000916113a3575b50158561135d565b6113bc915060203d6020116102bb576102ad8183611429565b8561139b565b600435906001600160a01b03821682036100cc57565b608081019081106001600160401b038211176105d357604052565b606081019081106001600160401b038211176105d357604052565b602081019081106001600160401b038211176105d357604052565b90601f801991011681019081106001600160401b038211176105d357604052565b6001600160401b0381116105d357601f01601f191660200190565b81601f820112156100cc5780359061147c8261144a565b9261148a6040519485611429565b828452602083830101116100cc57816000926020809301838601378301015290565b60005b8381106114bf5750506000910152565b81810151838201526020016114af565b906020916114e8815180928185528580860191016114ac565b601f01601f1916010190565b90600182811c92168015611524575b602083101461150e57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611503565b90604051918260008254611541816114f4565b908184526020946001916001811690816000146115b15750600114611572575b50505061157092500383611429565b565b600090815285812095935091905b8183106115995750506115709350820101388080611561565b85548884018501529485019487945091830191611580565b9250505061157094925060ff191682840152151560051b820101388080611561565b939261160f906116016000946115f360609560808a5260808a01906114cf565b9088820360208a01526114cf565b9086820360408801526114cf565b930152565b9493926116016060936115f361160f9460808a5260808a01906114cf565b908160209103126100cc575180151581036100cc5790565b901561176757600090338252602082815260408320916040519061166d826113d8565b6116768461152e565b825260019160036116896001870161152e565b9585830196875261169c6002820161152e565b604084015201546060820152519182511561176357908160216116be83611e66565b6116ca60018201611e34565b9850880101905b61172c575b505050611729925160405194826116f687945180928780880191016114ac565b830161170a825180938780850191016114ac565b0161171d825180938680850191016114ac565b01038084520182611429565b90565b6000190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561175e579190826116d1565b6116d6565b8580fd5b611729906117b2565b81601f820112156100cc5780516117868161144a565b926117946040519485611429565b818452602082840101116100cc5761172991602080850191016114ac565b6000903382526001602091600183526040918285208351926117d3846113f3565b6117dc8261152e565b84526117fc60026117ef6001850161152e565b938887019485520161152e565b85850190808252835151159081611a21575b50611a1d5785516306fdde0360e01b8152948886600481335afa958615611a135789966119c4575b50519251905191939161184891611f41565b9281602161185583611e66565b61186160018201611e34565b9a508a0101905b61198d575b50505061197d9561193f60446117299795879561194495603d9951958693693d913730b6b2911d101160b11b8b8601526118b0815180928d602a890191016114ac565b840161202360f01b602a8201526118d0825180938d602c850191016114ac565b0190631116101160e11b9182602c8201526e3232b9b1b934b83a34b7b7111d101160891b603082015261190c825180938d603f850191016114ac565b0190603f820152611926825180938b6043850191016114ac565b01607d60f81b6043820152036024810184520182611429565b61209b565b905194827f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008794850152825192839186860191016114ac565b810103601d810184520182611429565b6000190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156119bf57919082611868565b61186d565b9095503d808a833e6119d68183611429565b8101908881830312611a0f578051906001600160401b038211611a0b5791611a0391611848949301611770565b959091611836565b8a80fd5b8980fd5b87513d8b823e3d90fd5b8780fd5b905051153861180e565b9060405190611a39826113f3565b815282602082015283604082015260018060a01b0382166000526001602052604060002081518051906001600160401b0382116105d3578190611a7c84546114f4565b601f8111611de4575b50602090601f8311600114611d7e57600092611d73575b50508160011b916000199060031b1c19161781555b60208201518051906001600160401b0382116105d357611ad460018401546114f4565b601f8111611d2c575b50602090601f8311600114611cb957918060409492600294600092611cae575b50508160011b916000199060031b1c19161760018201555b019101518051906001600160401b0382116105d357611b3483546114f4565b601f8111611c66575b50602090601f8311600114611bd4579282611bc493611bab96937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e09896600092611bc9575b50508160011b916000199060031b1c19161790555b6040519384936040855260408501906114cf565b83810360208501526001600160a01b03909116956114cf565b0390a2565b015190503880611b82565b90601f198316918460005260206000209260005b818110611c4e575093611bab96937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098969360019383611bc49810611c35575b505050811b019055611b97565b015160001960f88460031b161c19169055388080611c28565b92936020600181928786015181550195019301611be8565b836000526020600020601f840160051c81019160208510611ca4575b601f0160051c01905b818110611c985750611b3d565b60008155600101611c8b565b9091508190611c82565b015190503880611afd565b90601f198316916001850160005260206000209260005b818110611d1457509260019285926002966040989610611cfb575b505050811b016001820155611b15565b015160001960f88460031b161c19169055388080611ceb565b92936020600181928786015181550195019301611cd0565b600184016000526020600020601f840160051c810160208510611d6c575b601f830160051c82018110611d60575050611add565b60008155600101611d4a565b5080611d4a565b015190503880611a9c565b6000858152602081209350601f198516905b818110611dcc5750908460019594939210611db3575b505050811b018155611ab1565b015160001960f88460031b161c19169055388080611da6565b92936020600181928786015181550195019301611d90565b909150836000526020600020601f840160051c810160208510611e2d575b90849392915b601f830160051c82018110611e1e575050611a85565b60008155859450600101611e08565b5080611e02565b90611e3e8261144a565b611e4b6040519182611429565b8281528092611e5c601f199161144a565b0190602036910137565b6000907a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000080821015611f34575b50600a906d04ee2d6d415b85acef810000000080821015611f27575b50662386f26fc1000080821015611f1a575b506305f5e10080821015611f0d575b5061271080821015611f00575b506064811015611ef2575b1015611eec5790565b60010190565b606460029104920191611ee3565b6004910492019138611ed8565b6008910492019138611ecb565b6010910492019138611ebc565b6020910492019138611eaa565b604092509004600a611e8e565b805115159082511515918080612094575b61201257611fc55750611f735750604051611f6c8161140e565b6000815290565b611729603260405180937030b734b6b0ba34b7b72fbab936111d101160791b6020830152611fab8151809260206031860191016114ac565b8101601160f91b6031820152036012810184520182611429565b915050611729602a60405180936834b6b0b3b2911d101160b91b6020830152611ff88151809260206029860191016114ac565b8101601160f91b602982015203600a810184520182611429565b506117299150603f906040519384916834b6b0b3b2911d101160b91b60208401526120478151809260206029870191016114ac565b8201741116101130b734b6b0ba34b7b72fbab936111d101160591b602982015261207b825180936020603e850191016114ac565b01601160f91b603e82015203601f810184520182611429565b5082611f52565b8051156121ee576040516120ae816113f3565b604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040820152815191600292600281018091116121d8576003908190046001600160fe1b03811681036121d857612135906002959492951b611e34565b936020850193839284518501935b84811061218557505050505060039051068060011461217257600214612167575090565b603d90600019015390565b50603d9081600019820153600119015390565b8360049197929394959701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c168801015188850153168501015186820153019593929190612143565b634e487b7160e01b600052601160045260246000fd5b50604051611f6c8161140e56fe5eff125d5659803f33dbda215d6e8bfe0a404fd213a9ecb5e61973ee16cb17e7a26469706673582212200cd9281c150da3ed18001c095f5f66dc5d3bfc497fe570897ac56a4f29fe31f864736f6c63430008190033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c80630bafbe08146112dc578063301a3260146112b057806342495a9514610da75780636bbde0011461085357806391074f98146107ed578063af806d56146102ce578063cc1306db146101df578063d644beac14610154578063de5af49b1461011a578063e8a3d485146100d15763ea58a14d1461009557600080fd5b346100cc5760203660031901126100cc576100c86100b46004356117b2565b6040519182916020835260208301906114cf565b0390f35b600080fd5b346100cc5760003660031901126100cc573360005260006020526100fb600260406000200161152e565b8051156100cc576100c8906040519182916020835260208301906114cf565b346100cc5760203660031901126100cc576001600160a01b0361013b6113c2565b1660005260026020526020604060002054604051908152f35b346100cc5760203660031901126100cc576001600160a01b036101756113c2565b1660005260016020526101c360406000206100c86101928261152e565b916101d16101ae60026101a76001850161152e565b930161152e565b916040519586956060875260608701906114cf565b9085820360208701526114cf565b9083820360408501526114cf565b346100cc5760403660031901126100cc576101f86113c2565b6001600160a01b03166024353382141580610260575b61024e5760207ff2e078c4022bfd6c56addd06540a4a5dd4252b6b2c424b6840c184063f48fc2791836000526002825280604060002055604051908152a2005b6040516302bd6bd160e01b8152600490fd5b50604051630935e01b60e21b8152336004820152602081602481865afa9081156102c257600091610293575b501561020e565b6102b5915060203d6020116102bb575b6102ad8183611429565b810190611632565b8361028c565b503d6102a3565b6040513d6000823e3d90fd5b346100cc5760603660031901126100cc576102e76113c2565b6024356001600160401b0381116100cc57610306903690600401611465565b6044356001600160401b0381116100cc57610325903690600401611465565b916001600160a01b03811633141580610792575b61024e576040519061034a8261140e565b60008083526001600160a01b0382168152602081905260409020600301548015159081610787575b506107755760405193610384856113d8565b8385528260208601528060408601526000606086015260018060a01b0382166000526000602052604060002085518051906001600160401b0382116105d35781906103cf84546114f4565b601f8111610725575b50602090601f83116001146106bf576000926106b4575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d357819061042960018501546114f4565b601f8111610661575b50602090601f83116001146105f4576000926105e9575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d35761048460028401546114f4565b601f811161058c575b506020601f8211600114610506576104f6949392826003936060936000805160206121fc8339815191529b9c6000926104fb575b50508160011b9160001990861b1c19161760028501555b01519101556040516001600160a01b039093169592938493846115d3565b0390a2005b015190508c806104c1565b601f198216986002850160005260206000209960005b8181106105745750836000805160206121fc8339815191529a9b6060946104f6999897946003976001951061055c575b505050811b0160028501556104d8565b015160001983881b60f8161c191690558c808061054c565b838301518c556001909b019a6020938401930161051c565b600284016000526020600020601f830160051c8101602084106105cc575b601f830160051c820181106105c057505061048d565b600081556001016105aa565b50806105aa565b634e487b7160e01b600052604160045260246000fd5b015190508880610449565b600185016000908152602081209350601f198516905b8181106106495750908460019594939210610630575b505050811b016001820155610461565b015160001960f88460031b161c19169055888080610620565b9293602060018192878601518155019501930161060a565b909150600184016000526020600020601f840160051c8101602085106106ad575b90849392915b601f830160051c8201811061069e575050610432565b60008155859450600101610688565b5080610682565b0151905088806103ef565b6000858152602081209350601f198516905b81811061070d57509084600195949392106106f4575b505050811b018155610404565b015160001960f88460031b161c191690558880806106e7565b929360206001819287860151815501950193016106d1565b909150836000526020600020601f840160051c81016020851061076e575b90849392915b601f830160051c8201811061075f5750506103d8565b60008155859450600101610749565b5080610743565b60405163777821ff60e11b8152600490fd5b905042101585610372565b50604051630935e01b60e21b81523360048201526020816024816001600160a01b0386165afa9081156102c2576000916107ce575b5015610339565b6107e7915060203d6020116102bb576102ad8183611429565b846107c7565b346100cc5760203660031901126100cc576001600160a01b0361080e6113c2565b16600052600060205260406000206108258161152e565b6100c86108346001840161152e565b9260036108436002830161152e565b9101549060405194859485611614565b346100cc5760403660031901126100cc576004356001600160401b0381116100cc57610883903690600401611465565b6024356001600160401b0381116100cc576108a2903690600401611465565b81518061093a575b5080915051806108b657005b8101606082602083019203126100cc5760208201516001600160401b0381116100cc578160206108e892850101611770565b9060408301516001600160401b0381116100cc5781602061090b92860101611770565b906060840151906001600160401b0382116100cc57602061093192610938960101611770565b9133611a2b565b005b820191604081602085019403126100cc5760208101516001600160401b0381116100cc5783602061096d92840101611770565b926040820151916001600160401b0383116100cc5761098f9201602001611770565b916040519261099d8461140e565b600084523360005260006020526003604060002001548015159081610d9c575b5061077557604051936109cf856113d8565b82855280602086015281604086015260006060860152336000526000602052604060002085518051906001600160401b0382116105d3578190610a1284546114f4565b601f8111610d4c575b50602090601f8311600114610ce657600092610cdb575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d3578190610a6c60018501546114f4565b601f8111610c88575b50602090601f8311600114610c1657600092610c0b575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d357610ac760028401546114f4565b601f8111610bc4575b506020601f8211600114610b425791816060926003946000805160206121fc833981519152999a9b600092610b37575b50508160011b9160001990861b1c19161760028501555b0151910155610b2d6040519283923396846115d3565b0390a280826108aa565b015190508b80610b00565b601f198216986002850160005260206000209960005b818110610bac5750926000805160206121fc83398151915298999a600395936001938360609710610b94575b505050811b016002850155610b17565b015160001983881b60f8161c191690558b8080610b84565b838301518c556001909b019a60209384019301610b58565b600284016000526020600020601f830160051c810160208410610c04575b601f830160051c82018110610bf8575050610ad0565b60008155600101610be2565b5080610be2565b015190508880610a8c565b9250600184016000526020600020906000935b601f1984168510610c6d576001945083601f19811610610c54575b505050811b016001820155610aa4565b015160001960f88460031b161c19169055888080610c44565b81810151835560209485019460019093019290910190610c29565b909150600184016000526020600020601f840160051c810160208510610cd4575b90849392915b601f830160051c82018110610cc5575050610a75565b60008155859450600101610caf565b5080610ca9565b015190508880610a32565b6000858152602081209350601f198516905b818110610d345750908460019594939210610d1b575b505050811b018155610a47565b015160001960f88460031b161c19169055888080610d0e565b92936020600181928786015181550195019301610cf8565b909150836000526020600020601f840160051c810160208510610d95575b90849392915b601f830160051c82018110610d86575050610a1b565b60008155859450600101610d70565b5080610d6a565b9050421015856109bd565b346100cc5760a03660031901126100cc57610dc06113c2565b6024356001600160401b0381116100cc57610ddf903690600401611465565b906044356001600160401b0381116100cc57610dff903690600401611465565b906064356001600160401b0381116100cc57610e1f903690600401611465565b906001600160a01b03811633141580611255575b61024e576001600160a01b038116600090815260208190526040902060030154801515908161124a575b506107755760405193610e6f856113d8565b808552836020860152826040860152608435606086015260018060a01b0382166000526000602052604060002085518051906001600160401b0382116105d3578190610ebb84546114f4565b601f81116111fa575b50602090601f831160011461119457600092611189575b50508160011b916000199060031b1c19161781555b60208601518051906001600160401b0382116105d3578190610f1560018501546114f4565b601f8111611136575b50602090601f83116001146110c9576000926110be575b50508160011b916000199060031b1c19161760018201555b60408601519586516001600160401b0381116105d357610f7060028401546114f4565b601f8111611077575b506020601f8211600114610ff1576104f6949392826003936060936000805160206121fc8339815191529b9c600092610fe6575b50508160011b9160001990861b1c19161760028501555b01519101556040516001600160a01b0390931695929384936084359285611614565b015190508c80610fad565b601f198216986002850160005260206000209960005b81811061105f5750836000805160206121fc8339815191529a9b6060946104f69998979460039760019510611047575b505050811b016002850155610fc4565b015160001983881b60f8161c191690558c8080611037565b838301518c556001909b019a60209384019301611007565b600284016000526020600020601f830160051c8101602084106110b7575b601f830160051c820181106110ab575050610f79565b60008155600101611095565b5080611095565b015190508880610f35565b600185016000908152602081209350601f198516905b81811061111e5750908460019594939210611105575b505050811b016001820155610f4d565b015160001960f88460031b161c191690558880806110f5565b929360206001819287860151815501950193016110df565b909150600184016000526020600020601f840160051c810160208510611182575b90849392915b601f830160051c82018110611173575050610f1e565b6000815585945060010161115d565b5080611157565b015190508880610edb565b6000858152602081209350601f198516905b8181106111e257509084600195949392106111c9575b505050811b018155610ef0565b015160001960f88460031b161c191690558880806111bc565b929360206001819287860151815501950193016111a6565b909150836000526020600020601f840160051c810160208510611243575b90849392915b601f830160051c82018110611234575050610ec4565b6000815585945060010161121e565b5080611218565b905042101585610e5d565b50604051630935e01b60e21b81523360048201526020816024816001600160a01b0386165afa9081156102c257600091611291575b5015610e33565b6112aa915060203d6020116102bb576102ad8183611429565b8561128a565b346100cc5760403660031901126100cc5760243580151581036100cc576100b46100c89160043561164a565b346100cc5760803660031901126100cc576112f56113c2565b6001600160401b036024358181116100cc57611315903690600401611465565b906044358181116100cc5761132e903690600401611465565b906064359081116100cc57611347903690600401611465565b916001600160a01b03841633811415908161136b575b5061024e5761093893611a2b565b604051630935e01b60e21b81523360048201529150602090829060249082905afa9081156102c2576000916113a3575b50158561135d565b6113bc915060203d6020116102bb576102ad8183611429565b8561139b565b600435906001600160a01b03821682036100cc57565b608081019081106001600160401b038211176105d357604052565b606081019081106001600160401b038211176105d357604052565b602081019081106001600160401b038211176105d357604052565b90601f801991011681019081106001600160401b038211176105d357604052565b6001600160401b0381116105d357601f01601f191660200190565b81601f820112156100cc5780359061147c8261144a565b9261148a6040519485611429565b828452602083830101116100cc57816000926020809301838601378301015290565b60005b8381106114bf5750506000910152565b81810151838201526020016114af565b906020916114e8815180928185528580860191016114ac565b601f01601f1916010190565b90600182811c92168015611524575b602083101461150e57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611503565b90604051918260008254611541816114f4565b908184526020946001916001811690816000146115b15750600114611572575b50505061157092500383611429565b565b600090815285812095935091905b8183106115995750506115709350820101388080611561565b85548884018501529485019487945091830191611580565b9250505061157094925060ff191682840152151560051b820101388080611561565b939261160f906116016000946115f360609560808a5260808a01906114cf565b9088820360208a01526114cf565b9086820360408801526114cf565b930152565b9493926116016060936115f361160f9460808a5260808a01906114cf565b908160209103126100cc575180151581036100cc5790565b901561176757600090338252602082815260408320916040519061166d826113d8565b6116768461152e565b825260019160036116896001870161152e565b9585830196875261169c6002820161152e565b604084015201546060820152519182511561176357908160216116be83611e66565b6116ca60018201611e34565b9850880101905b61172c575b505050611729925160405194826116f687945180928780880191016114ac565b830161170a825180938780850191016114ac565b0161171d825180938680850191016114ac565b01038084520182611429565b90565b6000190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821561175e579190826116d1565b6116d6565b8580fd5b611729906117b2565b81601f820112156100cc5780516117868161144a565b926117946040519485611429565b818452602082840101116100cc5761172991602080850191016114ac565b6000903382526001602091600183526040918285208351926117d3846113f3565b6117dc8261152e565b84526117fc60026117ef6001850161152e565b938887019485520161152e565b85850190808252835151159081611a21575b50611a1d5785516306fdde0360e01b8152948886600481335afa958615611a135789966119c4575b50519251905191939161184891611f41565b9281602161185583611e66565b61186160018201611e34565b9a508a0101905b61198d575b50505061197d9561193f60446117299795879561194495603d9951958693693d913730b6b2911d101160b11b8b8601526118b0815180928d602a890191016114ac565b840161202360f01b602a8201526118d0825180938d602c850191016114ac565b0190631116101160e11b9182602c8201526e3232b9b1b934b83a34b7b7111d101160891b603082015261190c825180938d603f850191016114ac565b0190603f820152611926825180938b6043850191016114ac565b01607d60f81b6043820152036024810184520182611429565b61209b565b905194827f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008794850152825192839186860191016114ac565b810103601d810184520182611429565b6000190190600a906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156119bf57919082611868565b61186d565b9095503d808a833e6119d68183611429565b8101908881830312611a0f578051906001600160401b038211611a0b5791611a0391611848949301611770565b959091611836565b8a80fd5b8980fd5b87513d8b823e3d90fd5b8780fd5b905051153861180e565b9060405190611a39826113f3565b815282602082015283604082015260018060a01b0382166000526001602052604060002081518051906001600160401b0382116105d3578190611a7c84546114f4565b601f8111611de4575b50602090601f8311600114611d7e57600092611d73575b50508160011b916000199060031b1c19161781555b60208201518051906001600160401b0382116105d357611ad460018401546114f4565b601f8111611d2c575b50602090601f8311600114611cb957918060409492600294600092611cae575b50508160011b916000199060031b1c19161760018201555b019101518051906001600160401b0382116105d357611b3483546114f4565b601f8111611c66575b50602090601f8311600114611bd4579282611bc493611bab96937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e09896600092611bc9575b50508160011b916000199060031b1c19161790555b6040519384936040855260408501906114cf565b83810360208501526001600160a01b03909116956114cf565b0390a2565b015190503880611b82565b90601f198316918460005260206000209260005b818110611c4e575093611bab96937faeb55777aebd643816b537b1251e9b2d6ec76dacb36ac8991ec89c41953fd7e098969360019383611bc49810611c35575b505050811b019055611b97565b015160001960f88460031b161c19169055388080611c28565b92936020600181928786015181550195019301611be8565b836000526020600020601f840160051c81019160208510611ca4575b601f0160051c01905b818110611c985750611b3d565b60008155600101611c8b565b9091508190611c82565b015190503880611afd565b90601f198316916001850160005260206000209260005b818110611d1457509260019285926002966040989610611cfb575b505050811b016001820155611b15565b015160001960f88460031b161c19169055388080611ceb565b92936020600181928786015181550195019301611cd0565b600184016000526020600020601f840160051c810160208510611d6c575b601f830160051c82018110611d60575050611add565b60008155600101611d4a565b5080611d4a565b015190503880611a9c565b6000858152602081209350601f198516905b818110611dcc5750908460019594939210611db3575b505050811b018155611ab1565b015160001960f88460031b161c19169055388080611da6565b92936020600181928786015181550195019301611d90565b909150836000526020600020601f840160051c810160208510611e2d575b90849392915b601f830160051c82018110611e1e575050611a85565b60008155859450600101611e08565b5080611e02565b90611e3e8261144a565b611e4b6040519182611429565b8281528092611e5c601f199161144a565b0190602036910137565b6000907a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000080821015611f34575b50600a906d04ee2d6d415b85acef810000000080821015611f27575b50662386f26fc1000080821015611f1a575b506305f5e10080821015611f0d575b5061271080821015611f00575b506064811015611ef2575b1015611eec5790565b60010190565b606460029104920191611ee3565b6004910492019138611ed8565b6008910492019138611ecb565b6010910492019138611ebc565b6020910492019138611eaa565b604092509004600a611e8e565b805115159082511515918080612094575b61201257611fc55750611f735750604051611f6c8161140e565b6000815290565b611729603260405180937030b734b6b0ba34b7b72fbab936111d101160791b6020830152611fab8151809260206031860191016114ac565b8101601160f91b6031820152036012810184520182611429565b915050611729602a60405180936834b6b0b3b2911d101160b91b6020830152611ff88151809260206029860191016114ac565b8101601160f91b602982015203600a810184520182611429565b506117299150603f906040519384916834b6b0b3b2911d101160b91b60208401526120478151809260206029870191016114ac565b8201741116101130b734b6b0ba34b7b72fbab936111d101160591b602982015261207b825180936020603e850191016114ac565b01601160f91b603e82015203601f810184520182611429565b5082611f52565b8051156121ee576040516120ae816113f3565b604081527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040820152815191600292600281018091116121d8576003908190046001600160fe1b03811681036121d857612135906002959492951b611e34565b936020850193839284518501935b84811061218557505050505060039051068060011461217257600214612167575090565b603d90600019015390565b50603d9081600019820153600119015390565b8360049197929394959701918251600190603f9082828260121c16880101518453828282600c1c16880101518385015382828260061c168801015188850153168501015186820153019593929190612143565b634e487b7160e01b600052601160045260246000fd5b50604051611f6c8161140e56fe5eff125d5659803f33dbda215d6e8bfe0a404fd213a9ecb5e61973ee16cb17e7a26469706673582212200cd9281c150da3ed18001c095f5f66dc5d3bfc497fe570897ac56a4f29fe31f864736f6c63430008190033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
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.