Source Code
Overview
APE Balance
2 APE
More Info
ContractCreator
TokenTracker
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
VixensPixel
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /// @title Vixen's Pixel /// @author Mojo Labs pragma solidity ^0.8.26; import "./OwnableBasic.sol"; import "./ERC721AC.sol"; import "./BasicRoyalties.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/utils/Address.sol"; contract VixensPixel is OwnableBasic, ERC721AC, BasicRoyalties { using Address for address; using MerkleProof for bytes32[]; bytes32 public merkleRoot; uint256 public MaxperWallet = 10; uint256 public MaxperWalletWl = 2; uint256 public maxSupply = 130; uint256 public wlSupply = 130; uint256 public whiteListRate = 1; uint256 public mintRate = 2; uint256 public currentState = 0; string public baseURI; string public baseHiddenUri; bool public revealed; bool public frozen; mapping(address => uint256) public whiteListUsedAddresses; mapping(address => uint256) public usedAddresses; // Custom error error NotEnoughTokensLeft(); error ContractIsPaused(); error InvalidMintQuantity(); // Modifiers modifier whenNotFrozen() { require(!frozen, "Contract metadata is frozen"); _; } modifier isEOA { require(msg.sender == tx.origin, "Function must be called by an EOA"); _; } /// @notice Initializes the contract with the initial owner /// @param initialOwner The address of the initial owner of the contract /// @param royaltyReceiver_ is the royalty recipient /// @param royaltyFeeNumerator_ is the royalty percentage to set constructor(address initialOwner, address royaltyReceiver_, uint96 royaltyFeeNumerator_) ERC721AC("Vixen's Pixel", "VXP") Ownable(initialOwner) BasicRoyalties(royaltyReceiver_, royaltyFeeNumerator_){ } /// @notice Public mint /// @param quantity The number of tokens to mint function mint(uint256 quantity, bytes32[] calldata _merkleProof) external payable isEOA { // check if the value is at least 1 if (quantity < 1) revert InvalidMintQuantity(); // check if enough token balance if (totalSupply() + quantity > maxSupply) revert NotEnoughTokensLeft(); // check if the contract is paused | State 0 = Sales not active if (currentState == 0) revert ContractIsPaused(); // State 1 = Presale mint for whitelisted | State 2 = Public mint if (currentState == 1) { uint256 ownerMintedCount = whiteListUsedAddresses[msg.sender]; require( isWhitelisted(msg.sender, _merkleProof), "User is not whitelisted" ); require( totalSupply() + quantity <= wlSupply, "Not Enough Tokens Left" ); require( ownerMintedCount + quantity <= MaxperWalletWl, "Max NFT per address exceeded" ); require( msg.value >= whiteListRate * quantity, "Insufficient funds" ); } else if (currentState == 2) { uint256 ownerMintedCount = usedAddresses[msg.sender]; require( ownerMintedCount + quantity <= MaxperWallet, "Max NFT per address exceeded" ); require(msg.value >= mintRate * quantity, "Insufficient funds"); } _mint(msg.sender, quantity); if (currentState == 1) { whiteListUsedAddresses[msg.sender] += quantity; } else if (currentState == 2) { usedAddresses[msg.sender] += quantity; } } /// @notice a function that check for user address and verify its proof function isWhitelisted(address _user, bytes32[] calldata _merkleProof) public view returns (bool) { bytes32 leaf = keccak256(abi.encodePacked(_user)); return MerkleProof.verify(_merkleProof, merkleRoot, leaf); } /// @notice A function to check how many tokens are still claimable for the entered address function mintableAmountForUser(address _user) public view returns (uint256) { if (currentState == 1) { return MaxperWalletWl - whiteListUsedAddresses[_user]; } else if (currentState == 2) { return MaxperWallet - usedAddresses[_user]; } return 0; } /// @notice Airdrops a specified quantity of tokens to an address /// @dev Requires owner /// @param quantity The number of tokens to airdrop /// @param destination The address to receive the airdrop function airdrop(uint256 quantity, address destination) external onlyOwner { if (totalSupply() + quantity > maxSupply) { revert NotEnoughTokensLeft(); } _mint(destination, quantity); } /// @notice Overrides the start token ID to be 1 function _startTokenId() internal pure override returns (uint256) { return 1; } /// @notice This is an internal function that returns base URI function _baseURI() internal view override returns (string memory) { return baseURI; } /// @notice Returns the URI for a specific token ID /// @param tokenId The ID of the token to get the URI for function tokenURI(uint256 tokenId) public view override returns (string memory) { require( _exists(tokenId), "URI query for nonexistent token"); if(revealed == false) { return baseHiddenUri; } string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, _toString(tokenId), ".json")) : ""; } /// @notice Sets the Merkle root for verifying whitelisted addresses /// @dev Requires owner /// @param _merkleRoot The new Merkle root function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner { merkleRoot = _merkleRoot; } /// @notice Sets the max per wallet /// @dev Requires owner /// @param _limit Number to set as max per wallet function setMaxPerWallet(uint256 _limit) external onlyOwner { MaxperWallet = _limit; } /// @notice Sets the max per wallet (only for presale) /// @dev Requires owner /// @param _limit Number to set as max per wallet function setMaxPerWalletWl(uint256 _limit) external onlyOwner { MaxperWalletWl = _limit; } /// @notice Cut the supply /// @dev Requires owner /// @param _newsupply Max number of tokens function setMaxsupply(uint256 _newsupply) external onlyOwner { maxSupply = _newsupply; } /// @notice Sets the max supply (only for presale) /// @dev Requires owner /// @param _newsupply Max number of tokens function setWlsupply(uint256 _newsupply) external onlyOwner { wlSupply = _newsupply; } /// @notice Sets the selling price /// @dev Requires owner /// @param _newRate Amount in Wei function setMintRate(uint256 _newRate) external onlyOwner { mintRate = _newRate; } /// @notice Sets the selling price (only for presale) /// @dev Requires owner /// @param _newRate Amount in Wei function setWhiteListRate(uint256 _newRate) external onlyOwner { whiteListRate = _newRate; } /// @notice Reveals the NFTs /// @dev Requires owner /// @param _state (booleans true or false) function setRevealed(bool _state) external onlyOwner whenNotFrozen{ revealed = _state; } /// @notice Freezes the metadata for the token /// @dev Requires owner function freezeMetadata() external onlyOwner { frozen = true; } /// @notice Sets the base URI /// @dev Requires owner /// @param _newBaseURI The base URI for revealed NFTs function setBaseURI(string memory _newBaseURI) external onlyOwner whenNotFrozen { baseURI = _newBaseURI; } /// @notice Sets the hidden URI /// @dev Requires owner /// @param _newBaseHiddenUri The base URI for unrevealed NFTs function setBaseHiddenUri(string memory _newBaseHiddenUri) external onlyOwner whenNotFrozen { baseHiddenUri = _newBaseHiddenUri; } /// @notice Pauses the contract, preventing further minting /// @dev Requires owner function pause() external onlyOwner { currentState = 0; } /// @notice Activate Presale /// @dev Requires owner function setOnlyWhitelisted() external onlyOwner { currentState = 1; } /// @notice Activate Public mint /// @dev Requires owner function setPublic() external onlyOwner { currentState = 2; } /// @notice Withdraw funds from contract /// @dev Requires owner /// @param _amount Amount in Ether function withdraw(uint256 _amount) external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No funds to withdraw"); require(_amount <= balance, 'not enough funds'); payable(msg.sender).transfer(_amount); } /// @notice Withdraw all funds from contract /// @dev Requires owner function withdrawAll() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No funds to withdraw"); payable(msg.sender).transfer(balance); } /// @notice Function to change the royalty info /// @dev Requires owner /// @param feeNumerator Is the new royalty percentage, in basis points (out of 10,000) function setDefaultRoyalty(address receiver, uint96 feeNumerator) public { _requireCallerIsContractOwner(); _setDefaultRoyalty(receiver, feeNumerator); } /// @notice Sets the royalty information for a specific token id /// @dev Requires owner /// @param feeNumerator Is the new royalty percentage, in basis points (out of 10,000) function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) public { _requireCallerIsContractOwner(); _setTokenRoyalty(tokenId, receiver, feeNumerator); } /// @notice Override supportsInterface function function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721AC, ERC2981) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol) // This file was procedurally generated from scripts/generate/templates/MerkleProof.js. pragma solidity ^0.8.20; import {Hashes} from "./Hashes.sol"; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the Merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates Merkle trees that are safe * against this attack out of the box. * * IMPORTANT: Consider memory side-effects when using custom hashing functions * that access memory in an unsafe way. * * NOTE: This library supports proof verification for merkle trees built using * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving * leaf inclusion in trees built using non-commutative hashing functions requires * additional logic that is not supported by this library. */ library MerkleProof { /** *@dev The multiproof provided is not valid. */ error MerkleProofInvalidMultiproof(); /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. * * This version handles proofs in memory with the default hashing function. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leaves & pre-images are assumed to be sorted. * * This version handles proofs in memory with the default hashing function. */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. * * This version handles proofs in memory with a custom hashing function. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bool) { return processProof(proof, leaf, hasher) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leaves & pre-images are assumed to be sorted. * * This version handles proofs in memory with a custom hashing function. */ function processProof( bytes32[] memory proof, bytes32 leaf, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = hasher(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. * * This version handles proofs in calldata with the default hashing function. */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leaves & pre-images are assumed to be sorted. * * This version handles proofs in calldata with the default hashing function. */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. * * This version handles proofs in calldata with a custom hashing function. */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bool) { return processProofCalldata(proof, leaf, hasher) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leaves & pre-images are assumed to be sorted. * * This version handles proofs in calldata with a custom hashing function. */ function processProofCalldata( bytes32[] calldata proof, bytes32 leaf, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = hasher(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * This version handles multiproofs in memory with the default hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. * * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. * The `leaves` must be validated independently. See {processMultiProof}. */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * This version handles multiproofs in memory with the default hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not * validating the leaves elsewhere. */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofFlagsLen = proofFlags.length; // Check proof validity. if (leavesLen + proof.length != proofFlagsLen + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](proofFlagsLen); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < proofFlagsLen; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = Hashes.commutativeKeccak256(a, b); } if (proofFlagsLen > 0) { if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[proofFlagsLen - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * This version handles multiproofs in memory with a custom hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. * * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. * The `leaves` must be validated independently. See {processMultiProof}. */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bool) { return processMultiProof(proof, proofFlags, leaves, hasher) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * This version handles multiproofs in memory with a custom hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not * validating the leaves elsewhere. */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofFlagsLen = proofFlags.length; // Check proof validity. if (leavesLen + proof.length != proofFlagsLen + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](proofFlagsLen); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < proofFlagsLen; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = hasher(a, b); } if (proofFlagsLen > 0) { if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[proofFlagsLen - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * This version handles multiproofs in calldata with the default hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. * * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. * The `leaves` must be validated independently. See {processMultiProofCalldata}. */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * This version handles multiproofs in calldata with the default hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not * validating the leaves elsewhere. */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofFlagsLen = proofFlags.length; // Check proof validity. if (leavesLen + proof.length != proofFlagsLen + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](proofFlagsLen); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < proofFlagsLen; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = Hashes.commutativeKeccak256(a, b); } if (proofFlagsLen > 0) { if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[proofFlagsLen - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * This version handles multiproofs in calldata with a custom hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. * * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`. * The `leaves` must be validated independently. See {processMultiProofCalldata}. */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * This version handles multiproofs in calldata with a custom hashing function. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op, * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not * validating the leaves elsewhere. */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves, function(bytes32, bytes32) view returns (bytes32) hasher ) internal view returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofFlagsLen = proofFlags.length; // Check proof validity. if (leavesLen + proof.length != proofFlagsLen + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](proofFlagsLen); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < proofFlagsLen; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = hasher(a, b); } if (proofFlagsLen > 0) { if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[proofFlagsLen - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/common/ERC2981.sol"; /** * @title BasicRoyaltiesBase * @author Limit Break, Inc. * @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties. */ abstract contract BasicRoyaltiesBase is ERC2981 { event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator); event TokenRoyaltySet(uint256 indexed tokenId, address indexed receiver, uint96 feeNumerator); function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual override { super._setDefaultRoyalty(receiver, feeNumerator); emit DefaultRoyaltySet(receiver, feeNumerator); } function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual override { super._setTokenRoyalty(tokenId, receiver, feeNumerator); emit TokenRoyaltySet(tokenId, receiver, feeNumerator); } } /** * @title BasicRoyalties * @author Limit Break, Inc. * @notice Constructable BasicRoyalties Contract implementation. */ abstract contract BasicRoyalties is BasicRoyaltiesBase { constructor(address receiver, uint96 feeNumerator) { _setDefaultRoyalty(receiver, feeNumerator); } } /** * @title BasicRoyaltiesInitializable * @author Limit Break, Inc. * @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones. */ abstract contract BasicRoyaltiesInitializable is BasicRoyaltiesBase {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./CreatorTokenBase.sol"; import "./ERC721A.sol"; /** * @title ERC721AC * @author Limit Break, Inc. * @notice Extends Azuki's ERC721-A implementation with Creator Token functionality, which * allows the contract owner to update the transfer validation logic by managing a security policy in * an external transfer validation security policy registry. See {CreatorTokenTransferValidator}. */ abstract contract ERC721AC is ERC721A, CreatorTokenBase { constructor(string memory name_, string memory symbol_) CreatorTokenBase() ERC721A(name_, symbol_) {} function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(ICreatorToken).interfaceId || super.supportsInterface(interfaceId); } /// @dev Ties the erc721a _beforeTokenTransfers hook to more granular transfer validation logic function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual override { for (uint256 i = 0; i < quantity;) { _validateBeforeTransfer(from, to, startTokenId + i); unchecked { ++i; } } } /// @dev Ties the erc721a _afterTokenTransfer hook to more granular transfer validation logic function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual override { for (uint256 i = 0; i < quantity;) { _validateAfterTransfer(from, to, startTokenId + i); unchecked { ++i; } } } function _msgSenderERC721A() internal view virtual override returns (address) { return _msgSender(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./OwnablePermissions.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; abstract contract OwnableBasic is OwnablePermissions, Ownable { function _requireCallerIsContractOwner() internal view virtual override { _checkOwner(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/Context.sol"; abstract contract OwnablePermissions is Context { function _requireCallerIsContractOwner() internal view virtual; }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * The `_sequentialUpTo()` function can be overriden to enable spot mints * (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // The amount of tokens minted above `_sequentialUpTo()`. // We call these spot mints (i.e. non-sequential mints). uint256 private _spotMinted; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID for sequential mints. * * Override this function to change the starting token ID for sequential mints. * * Note: The value returned must never change after any tokens have been minted. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the maximum token ID (inclusive) for sequential mints. * * Override this function to return a value less than 2**256 - 1, * but greater than `_startTokenId()`, to enable spot (non-sequential) mints. * * Note: The value returned must never change after any tokens have been minted. */ function _sequentialUpTo() internal view virtual returns (uint256) { return type(uint256).max; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256 result) { // Counter underflow is impossible as `_burnCounter` cannot be incremented // more than `_currentIndex + _spotMinted - _startTokenId()` times. unchecked { // With spot minting, the intermediate `result` can be temporarily negative, // and the computation must be unchecked. result = _currentIndex - _burnCounter - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256 result) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { result = _currentIndex - _startTokenId(); if (_sequentialUpTo() != type(uint256).max) result += _spotMinted; } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } /** * @dev Returns the total number of tokens that are spot-minted. */ function _totalSpotMinted() internal view virtual returns (uint256) { return _spotMinted; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Returns whether the ownership slot at `index` is initialized. * An uninitialized slot does not necessarily mean that the slot has no owner. */ function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) { return _packedOwnerships[index] != 0; } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * @dev Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) { if (_startTokenId() <= tokenId) { packed = _packedOwnerships[tokenId]; if (tokenId > _sequentialUpTo()) { if (_packedOwnershipExists(packed)) return packed; _revert(OwnerQueryForNonexistentToken.selector); } // If the data at the starting slot does not exist, start the scan. if (packed == 0) { if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector); // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `tokenId` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. for (;;) { unchecked { packed = _packedOwnerships[--tokenId]; } if (packed == 0) continue; if (packed & _BITMASK_BURNED == 0) return packed; // Otherwise, the token is burned, and we must revert. // This handles the case of batch burned tokens, where only the burned bit // of the starting slot is set, and remaining slots are left uninitialized. _revert(OwnerQueryForNonexistentToken.selector); } } // Otherwise, the data exists and we can skip the scan. // This is possible because we have already achieved the target condition. // This saves 2143 gas on transfers of initialized tokens. // If the token is not burned, return `packed`. Otherwise, revert. if (packed & _BITMASK_BURNED == 0) return packed; } _revert(OwnerQueryForNonexistentToken.selector); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}. * * Requirements: * * - The caller must own the token or be an approved operator. */ function approve(address to, uint256 tokenId) public payable virtual override { _approve(to, tokenId, true); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector); return _tokenApprovals[tokenId].value; } /** * @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) public virtual override { _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool result) { if (_startTokenId() <= tokenId) { if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]); if (tokenId < _currentIndex) { uint256 packed; while ((packed = _packedOwnerships[tokenId]) == 0) --tokenId; result = packed & _BITMASK_BURNED == 0; } } } /** * @dev Returns whether `packed` represents a token that exists. */ function _packedOwnershipExists(uint256 packed) private pure returns (bool result) { assembly { // The following is equivalent to `owner != address(0) && burned == false`. // Symbolically tested. result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED)) } } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean. from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS)); if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. from, // `from`. toMasked, // `to`. tokenId // `tokenId`. ) } if (toMasked == 0) _revert(TransferToZeroAddress.selector); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @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 memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { _revert(TransferToNonERC721ReceiverImplementer.selector); } assembly { revert(add(32, reason), mload(reason)) } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) _revert(MintZeroQuantity.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); uint256 end = startTokenId + quantity; uint256 tokenId = startTokenId; if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); do { assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } // The `!=` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. } while (++tokenId != end); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) _revert(MintToZeroAddress.selector); if (quantity == 0) _revert(MintZeroQuantity.selector); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } while (index < end); // This prevents reentrancy to `_safeMint`. // It does not prevent reentrancy to `_safeMintSpot`. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } /** * @dev Mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * Emits a {Transfer} event for each mint. */ function _mintSpot(address to, uint256 tokenId) internal virtual { if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector); uint256 prevOwnershipPacked = _packedOwnerships[tokenId]; if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector); _beforeTokenTransfers(address(0), to, tokenId, 1); // Overflows are incredibly unrealistic. // The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1. // `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `true` (as `quantity == 1`). _packedOwnerships[tokenId] = _packOwnershipData( to, _nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked) ); // Updates: // - `balance += 1`. // - `numberMinted += 1`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1; // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } ++_spotMinted; } _afterTokenTransfers(address(0), to, tokenId, 1); } /** * @dev Safely mints a single token at `tokenId`. * * Note: A spot-minted `tokenId` that has been burned can be re-minted again. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}. * - `tokenId` must be greater than `_sequentialUpTo()`. * - `tokenId` must not exist. * * See {_mintSpot}. * * Emits a {Transfer} event. */ function _safeMintSpot( address to, uint256 tokenId, bytes memory _data ) internal virtual { _mintSpot(to, tokenId); unchecked { if (to.code.length != 0) { uint256 currentSpotMinted = _spotMinted; if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } // This prevents reentrancy to `_safeMintSpot`. // It does not prevent reentrancy to `_safeMint`. if (_spotMinted != currentSpotMinted) revert(); } } } /** * @dev Equivalent to `_safeMintSpot(to, tokenId, '')`. */ function _safeMintSpot(address to, uint256 tokenId) internal virtual { _safeMintSpot(to, tokenId, ''); } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Equivalent to `_approve(to, tokenId, false)`. */ function _approve(address to, uint256 tokenId) internal virtual { _approve(to, tokenId, false); } /** * @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: * * - `tokenId` must exist. * * Emits an {Approval} event. */ function _approve( address to, uint256 tokenId, bool approvalCheck ) internal virtual { address owner = ownerOf(tokenId); if (approvalCheck && _msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { _revert(ApprovalCallerNotOwnerNorApproved.selector); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./OwnablePermissions.sol"; import "./ICreatorToken.sol"; import "./ICreatorTokenTransferValidator.sol"; import "./TransferValidation.sol"; import "@openzeppelin/contracts/interfaces/IERC165.sol"; /** * @title CreatorTokenBase * @author Limit Break, Inc. * @notice CreatorTokenBase is an abstract contract that provides basic functionality for managing token * transfer policies through an implementation of ICreatorTokenTransferValidator. This contract is intended to be used * as a base for creator-specific token contracts, enabling customizable transfer restrictions and security policies. * * <h4>Features:</h4> * <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul> * <ul>TransferValidation: Implements the basic token transfer validation interface.</ul> * <ul>ICreatorToken: Implements the interface for creator tokens, providing view functions for token security policies.</ul> * * <h4>Benefits:</h4> * <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul> * <ul>Allows creators to enforce policies such as whitelisted operators and permitted contract receivers.</ul> * <ul>Can be easily integrated into other token contracts as a base contract.</ul> * * <h4>Intended Usage:</h4> * <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and * security policies.</ul> * <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the * creator token.</ul> */ abstract contract CreatorTokenBase is OwnablePermissions, TransferValidation, ICreatorToken { error CreatorTokenBase__InvalidTransferValidatorContract(); error CreatorTokenBase__SetTransferValidatorFirst(); address public constant DEFAULT_TRANSFER_VALIDATOR = address(0x0000721C310194CcfC01E523fc93C9cCcFa2A0Ac); TransferSecurityLevels public constant DEFAULT_TRANSFER_SECURITY_LEVEL = TransferSecurityLevels.One; uint120 public constant DEFAULT_OPERATOR_WHITELIST_ID = uint120(1); ICreatorTokenTransferValidator private transferValidator; /** * @notice Allows the contract owner to set the transfer validator to the official validator contract * and set the security policy to the recommended default settings. * @dev May be overridden to change the default behavior of an individual collection. */ function setToDefaultSecurityPolicy() public virtual { _requireCallerIsContractOwner(); setTransferValidator(DEFAULT_TRANSFER_VALIDATOR); ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setTransferSecurityLevelOfCollection(address(this), DEFAULT_TRANSFER_SECURITY_LEVEL); ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setOperatorWhitelistOfCollection(address(this), DEFAULT_OPERATOR_WHITELIST_ID); } /** * @notice Allows the contract owner to set the transfer validator to a custom validator contract * and set the security policy to their own custom settings. */ function setToCustomValidatorAndSecurityPolicy( address validator, TransferSecurityLevels level, uint120 operatorWhitelistId, uint120 permittedContractReceiversAllowlistId) public { _requireCallerIsContractOwner(); setTransferValidator(validator); ICreatorTokenTransferValidator(validator). setTransferSecurityLevelOfCollection(address(this), level); ICreatorTokenTransferValidator(validator). setOperatorWhitelistOfCollection(address(this), operatorWhitelistId); ICreatorTokenTransferValidator(validator). setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId); } /** * @notice Allows the contract owner to set the security policy to their own custom settings. * @dev Reverts if the transfer validator has not been set. */ function setToCustomSecurityPolicy( TransferSecurityLevels level, uint120 operatorWhitelistId, uint120 permittedContractReceiversAllowlistId) public { _requireCallerIsContractOwner(); ICreatorTokenTransferValidator validator = getTransferValidator(); if (address(validator) == address(0)) { revert CreatorTokenBase__SetTransferValidatorFirst(); } validator.setTransferSecurityLevelOfCollection(address(this), level); validator.setOperatorWhitelistOfCollection(address(this), operatorWhitelistId); validator.setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId); } /** * @notice Sets the transfer validator for the token contract. * * @dev Throws when provided validator contract is not the zero address and doesn't support * the ICreatorTokenTransferValidator interface. * @dev Throws when the caller is not the contract owner. * * @dev <h4>Postconditions:</h4> * 1. The transferValidator address is updated. * 2. The `TransferValidatorUpdated` event is emitted. * * @param transferValidator_ The address of the transfer validator contract. */ function setTransferValidator(address transferValidator_) public { _requireCallerIsContractOwner(); bool isValidTransferValidator = false; if(transferValidator_.code.length > 0) { try IERC165(transferValidator_).supportsInterface(type(ICreatorTokenTransferValidator).interfaceId) returns (bool supportsInterface) { isValidTransferValidator = supportsInterface; } catch {} } if(transferValidator_ != address(0) && !isValidTransferValidator) { revert CreatorTokenBase__InvalidTransferValidatorContract(); } emit TransferValidatorUpdated(address(transferValidator), transferValidator_); transferValidator = ICreatorTokenTransferValidator(transferValidator_); } /** * @notice Returns the transfer validator contract address for this token contract. */ function getTransferValidator() public view override returns (ICreatorTokenTransferValidator) { return transferValidator; } /** * @notice Returns the security policy for this token contract, which includes: * Transfer security level, operator whitelist id, permitted contract receiver allowlist id. */ function getSecurityPolicy() public view override returns (CollectionSecurityPolicy memory) { if (address(transferValidator) != address(0)) { return transferValidator.getCollectionSecurityPolicy(address(this)); } return CollectionSecurityPolicy({ transferSecurityLevel: TransferSecurityLevels.Zero, operatorWhitelistId: 0, permittedContractReceiversId: 0 }); } /** * @notice Returns the list of all whitelisted operators for this token contract. * @dev This can be an expensive call and should only be used in view-only functions. */ function getWhitelistedOperators() public view override returns (address[] memory) { if (address(transferValidator) != address(0)) { return transferValidator.getWhitelistedOperators( transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId); } return new address[](0); } /** * @notice Returns the list of permitted contract receivers for this token contract. * @dev This can be an expensive call and should only be used in view-only functions. */ function getPermittedContractReceivers() public view override returns (address[] memory) { if (address(transferValidator) != address(0)) { return transferValidator.getPermittedContractReceivers( transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId); } return new address[](0); } /** * @notice Checks if an operator is whitelisted for this token contract. * @param operator The address of the operator to check. */ function isOperatorWhitelisted(address operator) public view override returns (bool) { if (address(transferValidator) != address(0)) { return transferValidator.isOperatorWhitelisted( transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId, operator); } return false; } /** * @notice Checks if a contract receiver is permitted for this token contract. * @param receiver The address of the receiver to check. */ function isContractReceiverPermitted(address receiver) public view override returns (bool) { if (address(transferValidator) != address(0)) { return transferValidator.isContractReceiverPermitted( transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId, receiver); } return false; } /** * @notice Determines if a transfer is allowed based on the token contract's security policy. Use this function * to simulate whether or not a transfer made by the specified `caller` from the `from` address to the `to` * address would be allowed by this token's security policy. * * @notice This function only checks the security policy restrictions and does not check whether token ownership * or approvals are in place. * * @param caller The address of the simulated caller. * @param from The address of the sender. * @param to The address of the receiver. * @return True if the transfer is allowed, false otherwise. */ function isTransferAllowed(address caller, address from, address to) public view override returns (bool) { if (address(transferValidator) != address(0)) { try transferValidator.applyCollectionTransferPolicy(caller, from, to) { return true; } catch { return false; } } return true; } /** * @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy. * Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent * and calling _validateBeforeTransfer so that checks can be properly applied during token transfers. * * @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is * set to a non-zero address. * * @param caller The address of the caller. * @param from The address of the sender. * @param to The address of the receiver. */ function _preValidateTransfer( address caller, address from, address to, uint256 /*tokenId*/, uint256 /*value*/) internal virtual override { if (address(transferValidator) != address(0)) { transferValidator.applyCollectionTransferPolicy(caller, from, to); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol) pragma solidity ^0.8.20; import {IERC2981} from "../../interfaces/IERC2981.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator); /** * @dev The default royalty receiver is invalid. */ error ERC2981InvalidDefaultRoyaltyReceiver(address receiver); /** * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator); /** * @dev The royalty receiver for `tokenId` is invalid. */ error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver); /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) public view virtual returns (address receiver, uint256 amount) { RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId]; address royaltyReceiver = _royaltyInfo.receiver; uint96 royaltyFraction = _royaltyInfo.royaltyFraction; if (royaltyReceiver == address(0)) { royaltyReceiver = _defaultRoyaltyInfo.receiver; royaltyFraction = _defaultRoyaltyInfo.royaltyFraction; } uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator(); return (royaltyReceiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidDefaultRoyaltyReceiver(address(0)); } _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual { uint256 denominator = _feeDenominator(); if (feeNumerator > denominator) { // Royalty fee will exceed the sale price revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator); } if (receiver == address(0)) { revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0)); } _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol) pragma solidity ^0.8.20; /** * @dev Library of standard hash functions. * * _Available since v5.1._ */ library Hashes { /** * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs. * * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. */ function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a); } /** * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. */ function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) { assembly ("memory-safe") { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); /** * `_sequentialUpTo()` must be greater than `_startTokenId()`. */ error SequentialUpToTooSmall(); /** * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`. */ error SequentialMintExceedsLimit(); /** * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`. */ error SpotMintTokenIdTooSmall(); /** * Cannot mint over a token that already exists. */ error TokenAlreadyExists(); /** * The feature is not compatible with spot mints. */ error NotCompatibleWithSpotMints(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @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`, * 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 be 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, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * 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 payable; /** * @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 payable; /** * @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); // ============================================================= // IERC721Metadata // ============================================================= /** * @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); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/Context.sol"; /** * @title TransferValidation * @author Limit Break, Inc. * @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks. * Openzeppelin's ERC721 contract only provides hooks for before and after transfer. This allows * developers to validate or customize transfers within the context of a mint, a burn, or a transfer. */ abstract contract TransferValidation is Context { error ShouldNotMintToBurnAddress(); /// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks. function _validateBeforeTransfer(address from, address to, uint256 tokenId) internal virtual { bool fromZeroAddress = from == address(0); bool toZeroAddress = to == address(0); if(fromZeroAddress && toZeroAddress) { revert ShouldNotMintToBurnAddress(); } else if(fromZeroAddress) { _preValidateMint(_msgSender(), to, tokenId, msg.value); } else if(toZeroAddress) { _preValidateBurn(_msgSender(), from, tokenId, msg.value); } else { _preValidateTransfer(_msgSender(), from, to, tokenId, msg.value); } } /// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks. function _validateAfterTransfer(address from, address to, uint256 tokenId) internal virtual { bool fromZeroAddress = from == address(0); bool toZeroAddress = to == address(0); if(fromZeroAddress && toZeroAddress) { revert ShouldNotMintToBurnAddress(); } else if(fromZeroAddress) { _postValidateMint(_msgSender(), to, tokenId, msg.value); } else if(toZeroAddress) { _postValidateBurn(_msgSender(), from, tokenId, msg.value); } else { _postValidateTransfer(_msgSender(), from, to, tokenId, msg.value); } } /// @dev Optional validation hook that fires before a mint function _preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a mint function _postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires before a burn function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a burn function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires before a transfer function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a transfer function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IEOARegistry.sol"; import "./ITransferSecurityRegistry.sol"; import "./ITransferValidator.sol"; interface ICreatorTokenTransferValidator is ITransferSecurityRegistry, ITransferValidator, IEOARegistry {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./ICreatorTokenTransferValidator.sol"; interface ICreatorToken { event TransferValidatorUpdated(address oldValidator, address newValidator); function getTransferValidator() external view returns (ICreatorTokenTransferValidator); function getSecurityPolicy() external view returns (CollectionSecurityPolicy memory); function getWhitelistedOperators() external view returns (address[] memory); function getPermittedContractReceivers() external view returns (address[] memory); function isOperatorWhitelisted(address operator) external view returns (bool); function isContractReceiverPermitted(address receiver) external view returns (bool); function isTransferAllowed(address caller, address from, address to) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. * * NOTE: ERC-2981 allows setting the royalty to 100% of the price. In that case all the price would be sent to the * royalty receiver and 0 tokens to the seller. Contracts dealing with royalty should consider empty transfers. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./TransferPolicy.sol"; interface ITransferValidator { function applyCollectionTransferPolicy(address caller, address from, address to) external view; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./TransferPolicy.sol"; interface ITransferSecurityRegistry { event AddedToAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event CreatedAllowlist(AllowlistTypes indexed kind, uint256 indexed id, string indexed name); event ReassignedAllowlistOwnership(AllowlistTypes indexed kind, uint256 indexed id, address indexed newOwner); event RemovedFromAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event SetAllowlist(AllowlistTypes indexed kind, address indexed collection, uint120 indexed id); event SetTransferSecurityLevel(address indexed collection, TransferSecurityLevels level); function createOperatorWhitelist(string calldata name) external returns (uint120); function createPermittedContractReceiverAllowlist(string calldata name) external returns (uint120); function reassignOwnershipOfOperatorWhitelist(uint120 id, address newOwner) external; function reassignOwnershipOfPermittedContractReceiverAllowlist(uint120 id, address newOwner) external; function renounceOwnershipOfOperatorWhitelist(uint120 id) external; function renounceOwnershipOfPermittedContractReceiverAllowlist(uint120 id) external; function setTransferSecurityLevelOfCollection(address collection, TransferSecurityLevels level) external; function setOperatorWhitelistOfCollection(address collection, uint120 id) external; function setPermittedContractReceiverAllowlistOfCollection(address collection, uint120 id) external; function addOperatorToWhitelist(uint120 id, address operator) external; function addPermittedContractReceiverToAllowlist(uint120 id, address receiver) external; function removeOperatorFromWhitelist(uint120 id, address operator) external; function removePermittedContractReceiverFromAllowlist(uint120 id, address receiver) external; function getCollectionSecurityPolicy(address collection) external view returns (CollectionSecurityPolicy memory); function getWhitelistedOperators(uint120 id) external view returns (address[] memory); function getPermittedContractReceivers(uint120 id) external view returns (address[] memory); function isOperatorWhitelisted(uint120 id, address operator) external view returns (bool); function isContractReceiverPermitted(uint120 id, address receiver) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; interface IEOARegistry is IERC165 { function isVerifiedEOA(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; enum AllowlistTypes { Operators, PermittedContractReceivers } enum ReceiverConstraints { None, NoCode, EOA } enum CallerConstraints { None, OperatorWhitelistEnableOTC, OperatorWhitelistDisableOTC } enum StakerConstraints { None, CallerIsTxOrigin, EOA } enum TransferSecurityLevels { Zero, One, Two, Three, Four, Five, Six } struct TransferSecurityPolicy { CallerConstraints callerConstraints; ReceiverConstraints receiverConstraints; } struct CollectionSecurityPolicy { TransferSecurityLevels transferSecurityLevel; uint120 operatorWhitelistId; uint120 permittedContractReceiversId; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "remappings": [] }
[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"royaltyReceiver_","type":"address"},{"internalType":"uint96","name":"royaltyFeeNumerator_","type":"uint96"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"ContractIsPaused","type":"error"},{"inputs":[],"name":"CreatorTokenBase__InvalidTransferValidatorContract","type":"error"},{"inputs":[],"name":"CreatorTokenBase__SetTransferValidatorFirst","type":"error"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"InvalidMintQuantity","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotCompatibleWithSpotMints","type":"error"},{"inputs":[],"name":"NotEnoughTokensLeft","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"SequentialMintExceedsLimit","type":"error"},{"inputs":[],"name":"SequentialUpToTooSmall","type":"error"},{"inputs":[],"name":"ShouldNotMintToBurnAddress","type":"error"},{"inputs":[],"name":"SpotMintTokenIdTooSmall","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"TokenRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":false,"internalType":"address","name":"newValidator","type":"address"}],"name":"TransferValidatorUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_OPERATOR_WHITELIST_ID","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_SECURITY_LEVEL","outputs":[{"internalType":"enum TransferSecurityLevels","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_VALIDATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxperWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxperWalletWl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"address","name":"destination","type":"address"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseHiddenUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPermittedContractReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSecurityPolicy","outputs":[{"components":[{"internalType":"enum TransferSecurityLevels","name":"transferSecurityLevel","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversId","type":"uint120"}],"internalType":"struct CollectionSecurityPolicy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferValidator","outputs":[{"internalType":"contract ICreatorTokenTransferValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistedOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"isContractReceiverPermitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"isTransferAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"mintableAmountForUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseHiddenUri","type":"string"}],"name":"setBaseHiddenUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setMaxPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setMaxPerWalletWl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newsupply","type":"uint256"}],"name":"setMaxsupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRate","type":"uint256"}],"name":"setMintRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setOnlyWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"},{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomValidatorAndSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToDefaultSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transferValidator_","type":"address"}],"name":"setTransferValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRate","type":"uint256"}],"name":"setWhiteListRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newsupply","type":"uint256"}],"name":"setWlsupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedAddresses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whiteListRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whiteListUsedAddresses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wlSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600a600e556002600f5560826010556082601155600160125560026013555f601455348015610031575f80fd5b506040516139c13803806139c183398101604081905261005091610271565b81816040518060400160405280600d81526020016c159a5e195b89dcc8141a5e195b609a1b8152506040518060400160405280600381526020016205658560ec1b81525086828281600290816100a69190610359565b5060036100b38282610359565b5060015f5550506001600160a01b0381166100e857604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100f18161010e565b505050610104828261015f60201b60201c565b5050505050610413565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b61016982826101b4565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b6127106001600160601b0382168110156101f357604051636f483d0960e01b81526001600160601b0383166004820152602481018290526044016100df565b6001600160a01b03831661021c57604051635b6cc80560e11b81525f60048201526024016100df565b50604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600b55565b80516001600160a01b038116811461026c575f80fd5b919050565b5f805f60608486031215610283575f80fd5b61028c84610256565b925061029a60208501610256565b60408501519092506001600160601b03811681146102b6575f80fd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806102e957607f821691505b60208210810361030757634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561035457805f5260205f20601f840160051c810160208510156103325750805b601f840160051c820191505b81811015610351575f815560010161033e565b50505b505050565b81516001600160401b03811115610372576103726102c1565b6103868161038084546102d5565b8461030d565b6020601f8211600181146103b8575f83156103a15750848201515b5f19600385901b1c1916600184901b178455610351565b5f84815260208120601f198516915b828110156103e757878501518255602094850194600190920191016103c7565b508482101561040457868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6135a1806104205f395ff3fe6080604052600436106103de575f3560e01c80636352211e116101ff578063ba41b0c611610113578063d5abeb01116100a8578063e79cb42a11610078578063e79cb42a14610b08578063e985e9c514610b1d578063f2fde38b14610b64578063fd571e0914610b83578063fd762d9214610ba2575f80fd5b8063d5abeb0114610a96578063dbe2193f14610aab578063e0a8085314610aca578063e268e4d314610ae9575f80fd5b8063c87b56dd116100e3578063c87b56dd14610a3a578063ca0dcf1614610a59578063d007af5c14610a6e578063d111515d14610a82575f80fd5b8063ba41b0c6146109d2578063bc63f02e146109e5578063bd7a199814610a04578063be537f4314610a19575f80fd5b8063853828b6116101945780639d645a44116101645780639d645a4414610937578063a22cb46514610956578063a9fc664e14610975578063acdce27314610994578063b88d4fde146109bf575f80fd5b8063853828b6146108de5780638da5cb5b146108f25780638fe11a971461090f57806395d89b4114610923575f80fd5b8063715018a6116101cf578063715018a61461088357806377e56357146108975780637cb64759146108ab5780638456cb59146108ca575f80fd5b80636352211e1461081d5780636c0360eb1461083c5780636c3b86991461085057806370a0823114610864575f80fd5b80631c33b328116102f657806342842e0e1161028b5780635944c7531161025b5780635944c753146107755780635a23dd99146107945780635d4c1d46146107b35780635dffc852146107df57806361347162146107fe575f80fd5b806342842e0e14610709578063495c8bf91461071c578063518302271461073d57806355f804b314610756575f80fd5b80632e1a7d4d116102c65780632e1a7d4d146106975780632e8da829146106b65780632eb4a7ab146106d55780633fe6feb9146106ea575f80fd5b80631c33b3281461061157806323b872dd14610632578063295e4c33146106455780632a55205a14610659575f80fd5b8063095ea7b31161037757806313bfabc01161034757806313bfabc01461056e578063149835a0146105995780631598279f146105b857806318160ddd146105d75780631b25b077146105f2575f80fd5b8063095ea7b314610514578063098144d4146105275780630c3f6acf146105445780630fe8418b14610559575f80fd5b8063054f7d9c116103b2578063054f7d9c1461049757806306fdde03146104b557806307656e33146104d6578063081812fc146104f5575f80fd5b806277ec05146103e2578063014635461461040a57806301ffc9a71461044757806304634d8d14610476575b5f80fd5b3480156103ed575f80fd5b506103f7600f5481565b6040519081526020015b60405180910390f35b348015610415575f80fd5b5061042f71721c310194ccfc01e523fc93c9cccfa2a0ac81565b6040516001600160a01b039091168152602001610401565b348015610452575f80fd5b50610466610461366004612b1d565b610bc1565b6040519015158152602001610401565b348015610481575f80fd5b50610495610490366004612b62565b610bd1565b005b3480156104a2575f80fd5b5060175461046690610100900460ff1681565b3480156104c0575f80fd5b506104c9610be7565b6040516104019190612bc3565b3480156104e1575f80fd5b506103f76104f0366004612bd5565b610c77565b348015610500575f80fd5b5061042f61050f366004612bf0565b610cdd565b610495610522366004612c07565b610d16565b348015610532575f80fd5b50600a546001600160a01b031661042f565b34801561054f575f80fd5b506103f760145481565b348015610564575f80fd5b506103f760115481565b348015610579575f80fd5b506103f7610588366004612bd5565b60186020525f908152604090205481565b3480156105a4575f80fd5b506104956105b3366004612bf0565b610d22565b3480156105c3575f80fd5b506104956105d2366004612ccf565b610d2f565b3480156105e2575f80fd5b506103f76001545f54035f190190565b3480156105fd575f80fd5b5061046661060c366004612d14565b610d74565b34801561061c575f80fd5b50610625600181565b6040516104019190612d7c565b610495610640366004612d8a565b610e09565b348015610650575f80fd5b50610495610f7d565b348015610664575f80fd5b50610678610673366004612dc8565b610f8c565b604080516001600160a01b039093168352602083019190915201610401565b3480156106a2575f80fd5b506104956106b1366004612bf0565b611011565b3480156106c1575f80fd5b506104666106d0366004612bd5565b6110d0565b3480156106e0575f80fd5b506103f7600d5481565b3480156106f5575f80fd5b50610495610704366004612bf0565b6111cf565b610495610717366004612d8a565b6111dc565b348015610727575f80fd5b506107306111f6565b6040516104019190612de8565b348015610748575f80fd5b506017546104669060ff1681565b348015610761575f80fd5b50610495610770366004612ccf565b611300565b348015610780575f80fd5b5061049561078f366004612e33565b61133c565b34801561079f575f80fd5b506104666107ae366004612eaf565b61134f565b3480156107be575f80fd5b506107c7600181565b6040516001600160781b039091168152602001610401565b3480156107ea575f80fd5b506104956107f9366004612bf0565b6113d3565b348015610809575f80fd5b50610495610818366004612f20565b6113e0565b348015610828575f80fd5b5061042f610837366004612bf0565b61153b565b348015610847575f80fd5b506104c9611545565b34801561085b575f80fd5b506104956115d1565b34801561086f575f80fd5b506103f761087e366004612bd5565b6116c0565b34801561088e575f80fd5b50610495611704565b3480156108a2575f80fd5b50610495611717565b3480156108b6575f80fd5b506104956108c5366004612bf0565b611726565b3480156108d5575f80fd5b50610495611733565b3480156108e9575f80fd5b50610495611741565b3480156108fd575f80fd5b506009546001600160a01b031661042f565b34801561091a575f80fd5b506104c96117b8565b34801561092e575f80fd5b506104c96117c5565b348015610942575f80fd5b50610466610951366004612bd5565b6117d4565b348015610961575f80fd5b50610495610970366004612f6a565b611899565b348015610980575f80fd5b5061049561098f366004612bd5565b611911565b34801561099f575f80fd5b506103f76109ae366004612bd5565b60196020525f908152604090205481565b6104956109cd366004612fa1565b611a30565b6104956109e036600461301c565b611a6b565b3480156109f0575f80fd5b506104956109ff36600461304b565b611e03565b348015610a0f575f80fd5b506103f7600e5481565b348015610a24575f80fd5b50610a2d611e51565b604051610401919061306e565b348015610a45575f80fd5b506104c9610a54366004612bf0565b611f08565b348015610a64575f80fd5b506103f760135481565b348015610a79575f80fd5b50610730612055565b348015610a8d575f80fd5b5061049561210c565b348015610aa1575f80fd5b506103f760105481565b348015610ab6575f80fd5b50610495610ac5366004612bf0565b612125565b348015610ad5575f80fd5b50610495610ae43660046130ac565b612132565b348015610af4575f80fd5b50610495610b03366004612bf0565b612175565b348015610b13575f80fd5b506103f760125481565b348015610b28575f80fd5b50610466610b373660046130c7565b6001600160a01b039182165f90815260076020908152604080832093909416825291909152205460ff1690565b348015610b6f575f80fd5b50610495610b7e366004612bd5565b612182565b348015610b8e575f80fd5b50610495610b9d366004612bf0565b6121bf565b348015610bad575f80fd5b50610495610bbc3660046130f3565b6121cc565b5f610bcb826122c1565b92915050565b610bd96122f5565b610be382826122fd565b5050565b606060028054610bf69061314c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c229061314c565b8015610c6d5780601f10610c4457610100808354040283529160200191610c6d565b820191905f5260205f20905b815481529060010190602001808311610c5057829003601f168201915b5050505050905090565b5f601454600103610ca7576001600160a01b0382165f90815260186020526040902054600f54610bcb9190613198565b601454600203610cd6576001600160a01b0382165f90815260196020526040902054600e54610bcb9190613198565b505f919050565b5f610ce782612352565b610cfb57610cfb6333d1c03960e21b61239c565b505f908152600660205260409020546001600160a01b031690565b610be3828260016123a4565b610d2a612445565b601055565b610d37612445565b601754610100900460ff1615610d685760405162461bcd60e51b8152600401610d5f906131ab565b60405180910390fd5b6016610be38282613226565b600a545f906001600160a01b031615610dfe57600a5460405163050bf71960e31b81526001600160a01b038681166004830152858116602483015284811660448301529091169063285fb8c8906064015f6040518083038186803b158015610dda575f80fd5b505afa925050508015610deb575060015b610df657505f610e02565b506001610e02565b5060015b9392505050565b5f610e1382612472565b6001600160a01b039485169490915081168414610e3957610e3962a1148160e81b61239c565b5f8281526006602052604090208054338082146001600160a01b03881690911417610e7c57610e688633610b37565b610e7c57610e7c632ce44b5f60e11b61239c565b610e89868686600161250b565b8015610e93575f82555b6001600160a01b038681165f9081526005602052604080822080545f19019055918716808252919020805460010190554260a01b17600160e11b175f85815260046020526040812091909155600160e11b84169003610f1f57600184015f818152600460205260408120549003610f1d575f548114610f1d575f8181526004602052604090208490555b505b6001600160a01b0385168481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4805f03610f6757610f67633a954ecd60e21b61239c565b610f748787876001612538565b50505050505050565b610f85612445565b6001601455565b5f828152600c6020526040812080548291906001600160a01b03811690600160a01b90046001600160601b031681610fdf575050600b546001600160a01b03811690600160a01b90046001600160601b03165b5f612710610ff66001600160601b038416896132e1565b61100091906132f8565b9295509193505050505b9250929050565b611019612445565b478061105e5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610d5f565b808211156110a15760405162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f7567682066756e647360801b6044820152606401610d5f565b604051339083156108fc029084905f818181858888f193505050501580156110cb573d5f803e3d5ffd5b505050565b600a545f906001600160a01b031615610cd657600a54604051635caaa2a960e11b81523060048201526001600160a01b039091169063d72dde5e90829063b955455290602401606060405180830381865afa158015611131573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111559190613317565b602001516040516001600160e01b031960e084901b1681526001600160781b0390911660048201526001600160a01b03851660248201526044015b602060405180830381865afa1580156111ab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bcb9190613389565b6111d7612445565b600f55565b6110cb83838360405180602001604052805f815250611a30565b600a546060906001600160a01b0316156112ee57600a54604051635caaa2a960e11b81523060048201526001600160a01b0390911690633fe5df9990829063b955455290602401606060405180830381865afa158015611258573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127c9190613317565b602001516040516001600160e01b031960e084901b1681526001600160781b0390911660048201526024015b5f60405180830381865afa1580156112c2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112e991908101906133a4565b905090565b50604080515f81526020810190915290565b611308612445565b601754610100900460ff16156113305760405162461bcd60e51b8152600401610d5f906131ab565b6015610be38282613226565b6113446122f5565b6110cb83838361255e565b6040516bffffffffffffffffffffffff19606085901b1660208201525f9081906034016040516020818303038152906040528051906020012090506113ca8484808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050600d5491508490506125b7565b95945050505050565b6113db612445565b601255565b6113e86122f5565b5f6113fb600a546001600160a01b031690565b90506001600160a01b03811661142457604051631cffe3dd60e11b815260040160405180910390fd5b604051630368065360e61b81526001600160a01b0382169063da0194c0906114529030908890600401613458565b5f604051808303815f87803b158015611469575f80fd5b505af115801561147b573d5f803e3d5ffd5b5050604051631182550160e11b81526001600160a01b0384169250632304aa0291506114ad9030908790600401613475565b5f604051808303815f87803b1580156114c4575f80fd5b505af11580156114d6573d5f803e3d5ffd5b505060405163235d10c560e21b81526001600160a01b0384169250638d74431491506115089030908690600401613475565b5f604051808303815f87803b15801561151f575f80fd5b505af1158015611531573d5f803e3d5ffd5b5050505050505050565b5f610bcb82612472565b601580546115529061314c565b80601f016020809104026020016040519081016040528092919081815260200182805461157e9061314c565b80156115c95780601f106115a0576101008083540402835291602001916115c9565b820191905f5260205f20905b8154815290600101906020018083116115ac57829003601f168201915b505050505081565b6115d96122f5565b6115f471721c310194ccfc01e523fc93c9cccfa2a0ac611911565b604051630368065360e61b815271721c310194ccfc01e523fc93c9cccfa2a0ac9063da0194c09061162c903090600190600401613458565b5f604051808303815f87803b158015611643575f80fd5b505af1158015611655573d5f803e3d5ffd5b5050604051631182550160e11b815271721c310194ccfc01e523fc93c9cccfa2a0ac9250632304aa029150611691903090600190600401613475565b5f604051808303815f87803b1580156116a8575f80fd5b505af11580156116ba573d5f803e3d5ffd5b50505050565b5f6001600160a01b0382166116df576116df6323d3ad8160e21b61239c565b506001600160a01b03165f9081526005602052604090205467ffffffffffffffff1690565b61170c612445565b6117155f6125cc565b565b61171f612445565b6002601455565b61172e612445565b600d55565b61173b612445565b5f601455565b611749612445565b478061178e5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610d5f565b604051339082156108fc029083905f818181858888f19350505050158015610be3573d5f803e3d5ffd5b601680546115529061314c565b606060038054610bf69061314c565b600a545f906001600160a01b031615610cd657600a54604051635caaa2a960e11b81523060048201526001600160a01b0390911690639445f53090829063b955455290602401606060405180830381865afa158015611835573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118599190613317565b60409081015190516001600160e01b031960e084901b1681526001600160781b0390911660048201526001600160a01b0385166024820152604401611190565b335f8181526007602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611905911515815260200190565b60405180910390a35050565b6119196122f5565b5f6001600160a01b0382163b15611992576040516301ffc9a760e01b81525f60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa92505050801561198a575060408051601f3d908101601f1916820190925261198791810190613389565b60015b156119925790505b6001600160a01b038216158015906119a8575080155b156119c6576040516332483afb60e01b815260040160405180910390fd5b600a54604080516001600160a01b03928316815291841660208301527fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac910160405180910390a150600a80546001600160a01b0319166001600160a01b0392909216919091179055565b611a3b848484610e09565b6001600160a01b0383163b156116ba57611a578484848461261d565b6116ba576116ba6368d2bf6b60e11b61239c565b333214611ac45760405162461bcd60e51b815260206004820152602160248201527f46756e6374696f6e206d7573742062652063616c6c656420627920616e20454f6044820152604160f81b6064820152608401610d5f565b6001831015611ae65760405163011674e560e71b815260040160405180910390fd5b60105483611af96001545f54035f190190565b611b039190613497565b1115611b22576040516376592c6f60e01b815260040160405180910390fd5b6014545f03611b44576040516306d39fcd60e41b815260040160405180910390fd5b601454600103611ccc57335f8181526018602052604090205490611b6990848461134f565b611bb55760405162461bcd60e51b815260206004820152601760248201527f55736572206973206e6f742077686974656c69737465640000000000000000006044820152606401610d5f565b60115484611bc86001545f54035f190190565b611bd29190613497565b1115611c195760405162461bcd60e51b8152602060048201526016602482015275139bdd08115b9bdd59da08151bdad95b9cc81319599d60521b6044820152606401610d5f565b600f54611c268583613497565b1115611c745760405162461bcd60e51b815260206004820152601c60248201527f4d6178204e4654207065722061646472657373206578636565646564000000006044820152606401610d5f565b83601254611c8291906132e1565b341015611cc65760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b6044820152606401610d5f565b50611d94565b601454600203611d9457335f90815260196020526040902054600e54611cf28583613497565b1115611d405760405162461bcd60e51b815260206004820152601c60248201527f4d6178204e4654207065722061646472657373206578636565646564000000006044820152606401610d5f565b83601354611d4e91906132e1565b341015611d925760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b6044820152606401610d5f565b505b611d9e33846126fc565b601454600103611dd157335f9081526018602052604081208054859290611dc6908490613497565b909155506110cb9050565b6014546002036110cb57335f9081526019602052604081208054859290611df9908490613497565b9091555050505050565b611e0b612445565b60105482611e1e6001545f54035f190190565b611e289190613497565b1115611e47576040516376592c6f60e01b815260040160405180910390fd5b610be381836126fc565b604080516060810182525f8082526020820181905291810191909152600a546001600160a01b031615611ee857600a54604051635caaa2a960e11b81523060048201526001600160a01b039091169063b955455290602401606060405180830381865afa158015611ec4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112e99190613317565b50604080516060810182525f808252602082018190529181019190915290565b6060611f1382612352565b611f5f5760405162461bcd60e51b815260206004820152601f60248201527f55524920717565727920666f72206e6f6e6578697374656e7420746f6b656e006044820152606401610d5f565b60175460ff1615155f03611ffd5760168054611f7a9061314c565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa69061314c565b8015611ff15780601f10611fc857610100808354040283529160200191611ff1565b820191905f5260205f20905b815481529060010190602001808311611fd457829003601f168201915b50505050509050919050565b5f6120066127cb565b90505f8151116120245760405180602001604052805f815250610e02565b8061202e846127da565b60405160200161203f9291906134c1565b6040516020818303038152906040529392505050565b600a546060906001600160a01b0316156112ee57600a54604051635caaa2a960e11b81523060048201526001600160a01b03909116906317e94a6c90829063b955455290602401606060405180830381865afa1580156120b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120db9190613317565b60409081015190516001600160e01b031960e084901b1681526001600160781b0390911660048201526024016112a8565b612114612445565b6017805461ff001916610100179055565b61212d612445565b601355565b61213a612445565b601754610100900460ff16156121625760405162461bcd60e51b8152600401610d5f906131ab565b6017805460ff1916911515919091179055565b61217d612445565b600e55565b61218a612445565b6001600160a01b0381166121b357604051631e4fbdf760e01b81525f6004820152602401610d5f565b6121bc816125cc565b50565b6121c7612445565b601155565b6121d46122f5565b6121dd84611911565b604051630368065360e61b81526001600160a01b0385169063da0194c09061220b9030908790600401613458565b5f604051808303815f87803b158015612222575f80fd5b505af1158015612234573d5f803e3d5ffd5b5050604051631182550160e11b81526001600160a01b0387169250632304aa0291506122669030908690600401613475565b5f604051808303815f87803b15801561227d575f80fd5b505af115801561228f573d5f803e3d5ffd5b505060405163235d10c560e21b81526001600160a01b0387169250638d74431491506115089030908590600401613475565b5f6001600160e01b0319821663152a902d60e11b1480610bcb57506301ffc9a760e01b6001600160e01b0319831614610bcb565b611715612445565b612307828261281d565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b5f81600111612397575f54821015612397575f5b505f828152600460205260408120549081900361238d57612386836134eb565b9250612366565b600160e01b161590505b919050565b805f5260045ffd5b5f6123ae8361153b565b90508180156123c65750336001600160a01b03821614155b156123e9576123d58133610b37565b6123e9576123e96367d9dca160e11b61239c565b5f8381526006602052604080822080546001600160a01b0319166001600160a01b0388811691821790925591518693918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b6009546001600160a01b031633146117155760405163118cdaa760e01b8152336004820152602401610d5f565b5f816001116124fb57505f81815260046020526040902054805f036124e9575f5482106124a9576124a9636f96cda160e11b61239c565b5b505f19015f8181526004602052604090205480156124aa57600160e01b81165f036124d457919050565b6124e4636f96cda160e11b61239c565b6124aa565b600160e01b81165f036124fb57919050565b612397636f96cda160e11b61239c565b5f5b818110156125315761252985856125248487613497565b6128bf565b60010161250d565b5050505050565b5f5b818110156125315761255685856125518487613497565b612915565b60010161253a565b61256983838361295c565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c9060200160405180910390a3505050565b5f826125c38584612a1c565b14949350505050565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b604051630a85bd0160e11b81525f906001600160a01b0385169063150b7a0290612651903390899088908890600401613500565b6020604051808303815f875af192505050801561268b575060408051601f3d908101601f191682019092526126889181019061353c565b60015b6126de573d8080156126b8576040519150601f19603f3d011682016040523d82523d5f602084013e6126bd565b606091505b5080515f036126d6576126d66368d2bf6b60e11b61239c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b5f8054908290036127175761271763b562e8dd60e01b61239c565b6127235f84838561250b565b5f8181526004602090815260408083206001600160a01b0387164260a01b6001881460e11b1781179091558084526005909252822080546801000000000000000186020190559081900361278057612780622e076360e81b61239c565b818301825b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a481816001019150810361278557505f9081556110cb9150848385612538565b606060158054610bf69061314c565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806127f35750819003601f19909101908152919050565b6127106001600160601b03821681101561285c57604051636f483d0960e01b81526001600160601b038316600482015260248101829052604401610d5f565b6001600160a01b03831661288557604051635b6cc80560e11b81525f6004820152602401610d5f565b50604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600b55565b6001600160a01b0383811615908316158180156128d95750805b156128f757604051635cbd944160e01b815260040160405180910390fd5b8115612903575b612531565b806128fe576125313386868634612a5e565b6001600160a01b03838116159083161581801561292f5750805b1561294d57604051635cbd944160e01b815260040160405180910390fd5b816128fe57806128fe57612531565b6127106001600160601b0382168110156129a25760405163dfd1fc1b60e01b8152600481018590526001600160601b038316602482015260448101829052606401610d5f565b6001600160a01b0383166129d257604051634b4f842960e11b8152600481018590525f6024820152604401610d5f565b506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182525f968752600c90529190942093519051909116600160a01b029116179055565b5f81815b8451811015612a5657612a4c82868381518110612a3f57612a3f613557565b6020026020010151612adf565b9150600101612a20565b509392505050565b600a546001600160a01b03161561253157600a5460405163050bf71960e31b81526001600160a01b038781166004830152868116602483015285811660448301529091169063285fb8c8906064015f6040518083038186803b158015612ac2575f80fd5b505afa158015612ad4573d5f803e3d5ffd5b505050505050505050565b5f818310612af9575f828152602084905260409020610e02565b505f9182526020526040902090565b6001600160e01b0319811681146121bc575f80fd5b5f60208284031215612b2d575f80fd5b8135610e0281612b08565b6001600160a01b03811681146121bc575f80fd5b80356001600160601b0381168114612397575f80fd5b5f8060408385031215612b73575f80fd5b8235612b7e81612b38565b9150612b8c60208401612b4c565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e026020830184612b95565b5f60208284031215612be5575f80fd5b8135610e0281612b38565b5f60208284031215612c00575f80fd5b5035919050565b5f8060408385031215612c18575f80fd5b8235612c2381612b38565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612c6e57612c6e612c31565b604052919050565b5f8067ffffffffffffffff841115612c9057612c90612c31565b50601f8301601f1916602001612ca581612c45565b915050828152838383011115612cb9575f80fd5b828260208301375f602084830101529392505050565b5f60208284031215612cdf575f80fd5b813567ffffffffffffffff811115612cf5575f80fd5b8201601f81018413612d05575f80fd5b6126f484823560208401612c76565b5f805f60608486031215612d26575f80fd5b8335612d3181612b38565b92506020840135612d4181612b38565b91506040840135612d5181612b38565b809150509250925092565b60078110612d7857634e487b7160e01b5f52602160045260245ffd5b9052565b60208101610bcb8284612d5c565b5f805f60608486031215612d9c575f80fd5b8335612da781612b38565b92506020840135612db781612b38565b929592945050506040919091013590565b5f8060408385031215612dd9575f80fd5b50508035926020909101359150565b602080825282518282018190525f918401906040840190835b81811015612e285783516001600160a01b0316835260209384019390920191600101612e01565b509095945050505050565b5f805f60608486031215612e45575f80fd5b833592506020840135612e5781612b38565b9150612e6560408501612b4c565b90509250925092565b5f8083601f840112612e7e575f80fd5b50813567ffffffffffffffff811115612e95575f80fd5b6020830191508360208260051b850101111561100a575f80fd5b5f805f60408486031215612ec1575f80fd5b8335612ecc81612b38565b9250602084013567ffffffffffffffff811115612ee7575f80fd5b612ef386828701612e6e565b9497909650939450505050565b600781106121bc575f80fd5b6001600160781b03811681146121bc575f80fd5b5f805f60608486031215612f32575f80fd5b8335612f3d81612f00565b92506020840135612f4d81612f0c565b91506040840135612d5181612f0c565b80151581146121bc575f80fd5b5f8060408385031215612f7b575f80fd5b8235612f8681612b38565b91506020830135612f9681612f5d565b809150509250929050565b5f805f8060808587031215612fb4575f80fd5b8435612fbf81612b38565b93506020850135612fcf81612b38565b925060408501359150606085013567ffffffffffffffff811115612ff1575f80fd5b8501601f81018713613001575f80fd5b61301087823560208401612c76565b91505092959194509250565b5f805f6040848603121561302e575f80fd5b83359250602084013567ffffffffffffffff811115612ee7575f80fd5b5f806040838503121561305c575f80fd5b823591506020830135612f9681612b38565b5f606082019050613080828451612d5c565b6001600160781b0360208401511660208301526001600160781b03604084015116604083015292915050565b5f602082840312156130bc575f80fd5b8135610e0281612f5d565b5f80604083850312156130d8575f80fd5b82356130e381612b38565b91506020830135612f9681612b38565b5f805f8060808587031215613106575f80fd5b843561311181612b38565b9350602085013561312181612f00565b9250604085013561313181612f0c565b9150606085013561314181612f0c565b939692955090935050565b600181811c9082168061316057607f821691505b60208210810361317e57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610bcb57610bcb613184565b6020808252601b908201527f436f6e7472616374206d657461646174612069732066726f7a656e0000000000604082015260600190565b601f8211156110cb57805f5260205f20601f840160051c810160208510156132075750805b601f840160051c820191505b81811015612531575f8155600101613213565b815167ffffffffffffffff81111561324057613240612c31565b6132548161324e845461314c565b846131e2565b6020601f821160018114613286575f831561326f5750848201515b5f19600385901b1c1916600184901b178455612531565b5f84815260208120601f198516915b828110156132b55787850151825560209485019460019092019101613295565b50848210156132d257868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b8082028115828204841417610bcb57610bcb613184565b5f8261331257634e487b7160e01b5f52601260045260245ffd5b500490565b5f6060828403128015613328575f80fd5b506040516060810167ffffffffffffffff8111828210171561334c5761334c612c31565b604052825161335a81612f00565b8152602083015161336a81612f0c565b6020820152604083015161337d81612f0c565b60408201529392505050565b5f60208284031215613399575f80fd5b8151610e0281612f5d565b5f602082840312156133b4575f80fd5b815167ffffffffffffffff8111156133ca575f80fd5b8201601f810184136133da575f80fd5b805167ffffffffffffffff8111156133f4576133f4612c31565b8060051b61340460208201612c45565b9182526020818401810192908101908784111561341f575f80fd5b6020850194505b8385101561344d578451925061343b83612b38565b82825260209485019490910190613426565b979650505050505050565b6001600160a01b038316815260408101610e026020830184612d5c565b6001600160a01b039290921682526001600160781b0316602082015260400190565b80820180821115610bcb57610bcb613184565b5f81518060208401855e5f93019283525090919050565b5f6134d56134cf83866134aa565b846134aa565b64173539b7b760d91b8152600501949350505050565b5f816134f9576134f9613184565b505f190190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061353290830184612b95565b9695505050505050565b5f6020828403121561354c575f80fd5b8151610e0281612b08565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220dd0738d8066e9ad5f833c3ac142499d0d134076f3a694674f62b4bbf7b3ff43e64736f6c634300081a00330000000000000000000000009364521aacba93f4309bd933254459f2d04f742e0000000000000000000000009364521aacba93f4309bd933254459f2d04f742e000000000000000000000000000000000000000000000000000000000000012c
Deployed Bytecode
0x6080604052600436106103de575f3560e01c80636352211e116101ff578063ba41b0c611610113578063d5abeb01116100a8578063e79cb42a11610078578063e79cb42a14610b08578063e985e9c514610b1d578063f2fde38b14610b64578063fd571e0914610b83578063fd762d9214610ba2575f80fd5b8063d5abeb0114610a96578063dbe2193f14610aab578063e0a8085314610aca578063e268e4d314610ae9575f80fd5b8063c87b56dd116100e3578063c87b56dd14610a3a578063ca0dcf1614610a59578063d007af5c14610a6e578063d111515d14610a82575f80fd5b8063ba41b0c6146109d2578063bc63f02e146109e5578063bd7a199814610a04578063be537f4314610a19575f80fd5b8063853828b6116101945780639d645a44116101645780639d645a4414610937578063a22cb46514610956578063a9fc664e14610975578063acdce27314610994578063b88d4fde146109bf575f80fd5b8063853828b6146108de5780638da5cb5b146108f25780638fe11a971461090f57806395d89b4114610923575f80fd5b8063715018a6116101cf578063715018a61461088357806377e56357146108975780637cb64759146108ab5780638456cb59146108ca575f80fd5b80636352211e1461081d5780636c0360eb1461083c5780636c3b86991461085057806370a0823114610864575f80fd5b80631c33b328116102f657806342842e0e1161028b5780635944c7531161025b5780635944c753146107755780635a23dd99146107945780635d4c1d46146107b35780635dffc852146107df57806361347162146107fe575f80fd5b806342842e0e14610709578063495c8bf91461071c578063518302271461073d57806355f804b314610756575f80fd5b80632e1a7d4d116102c65780632e1a7d4d146106975780632e8da829146106b65780632eb4a7ab146106d55780633fe6feb9146106ea575f80fd5b80631c33b3281461061157806323b872dd14610632578063295e4c33146106455780632a55205a14610659575f80fd5b8063095ea7b31161037757806313bfabc01161034757806313bfabc01461056e578063149835a0146105995780631598279f146105b857806318160ddd146105d75780631b25b077146105f2575f80fd5b8063095ea7b314610514578063098144d4146105275780630c3f6acf146105445780630fe8418b14610559575f80fd5b8063054f7d9c116103b2578063054f7d9c1461049757806306fdde03146104b557806307656e33146104d6578063081812fc146104f5575f80fd5b806277ec05146103e2578063014635461461040a57806301ffc9a71461044757806304634d8d14610476575b5f80fd5b3480156103ed575f80fd5b506103f7600f5481565b6040519081526020015b60405180910390f35b348015610415575f80fd5b5061042f71721c310194ccfc01e523fc93c9cccfa2a0ac81565b6040516001600160a01b039091168152602001610401565b348015610452575f80fd5b50610466610461366004612b1d565b610bc1565b6040519015158152602001610401565b348015610481575f80fd5b50610495610490366004612b62565b610bd1565b005b3480156104a2575f80fd5b5060175461046690610100900460ff1681565b3480156104c0575f80fd5b506104c9610be7565b6040516104019190612bc3565b3480156104e1575f80fd5b506103f76104f0366004612bd5565b610c77565b348015610500575f80fd5b5061042f61050f366004612bf0565b610cdd565b610495610522366004612c07565b610d16565b348015610532575f80fd5b50600a546001600160a01b031661042f565b34801561054f575f80fd5b506103f760145481565b348015610564575f80fd5b506103f760115481565b348015610579575f80fd5b506103f7610588366004612bd5565b60186020525f908152604090205481565b3480156105a4575f80fd5b506104956105b3366004612bf0565b610d22565b3480156105c3575f80fd5b506104956105d2366004612ccf565b610d2f565b3480156105e2575f80fd5b506103f76001545f54035f190190565b3480156105fd575f80fd5b5061046661060c366004612d14565b610d74565b34801561061c575f80fd5b50610625600181565b6040516104019190612d7c565b610495610640366004612d8a565b610e09565b348015610650575f80fd5b50610495610f7d565b348015610664575f80fd5b50610678610673366004612dc8565b610f8c565b604080516001600160a01b039093168352602083019190915201610401565b3480156106a2575f80fd5b506104956106b1366004612bf0565b611011565b3480156106c1575f80fd5b506104666106d0366004612bd5565b6110d0565b3480156106e0575f80fd5b506103f7600d5481565b3480156106f5575f80fd5b50610495610704366004612bf0565b6111cf565b610495610717366004612d8a565b6111dc565b348015610727575f80fd5b506107306111f6565b6040516104019190612de8565b348015610748575f80fd5b506017546104669060ff1681565b348015610761575f80fd5b50610495610770366004612ccf565b611300565b348015610780575f80fd5b5061049561078f366004612e33565b61133c565b34801561079f575f80fd5b506104666107ae366004612eaf565b61134f565b3480156107be575f80fd5b506107c7600181565b6040516001600160781b039091168152602001610401565b3480156107ea575f80fd5b506104956107f9366004612bf0565b6113d3565b348015610809575f80fd5b50610495610818366004612f20565b6113e0565b348015610828575f80fd5b5061042f610837366004612bf0565b61153b565b348015610847575f80fd5b506104c9611545565b34801561085b575f80fd5b506104956115d1565b34801561086f575f80fd5b506103f761087e366004612bd5565b6116c0565b34801561088e575f80fd5b50610495611704565b3480156108a2575f80fd5b50610495611717565b3480156108b6575f80fd5b506104956108c5366004612bf0565b611726565b3480156108d5575f80fd5b50610495611733565b3480156108e9575f80fd5b50610495611741565b3480156108fd575f80fd5b506009546001600160a01b031661042f565b34801561091a575f80fd5b506104c96117b8565b34801561092e575f80fd5b506104c96117c5565b348015610942575f80fd5b50610466610951366004612bd5565b6117d4565b348015610961575f80fd5b50610495610970366004612f6a565b611899565b348015610980575f80fd5b5061049561098f366004612bd5565b611911565b34801561099f575f80fd5b506103f76109ae366004612bd5565b60196020525f908152604090205481565b6104956109cd366004612fa1565b611a30565b6104956109e036600461301c565b611a6b565b3480156109f0575f80fd5b506104956109ff36600461304b565b611e03565b348015610a0f575f80fd5b506103f7600e5481565b348015610a24575f80fd5b50610a2d611e51565b604051610401919061306e565b348015610a45575f80fd5b506104c9610a54366004612bf0565b611f08565b348015610a64575f80fd5b506103f760135481565b348015610a79575f80fd5b50610730612055565b348015610a8d575f80fd5b5061049561210c565b348015610aa1575f80fd5b506103f760105481565b348015610ab6575f80fd5b50610495610ac5366004612bf0565b612125565b348015610ad5575f80fd5b50610495610ae43660046130ac565b612132565b348015610af4575f80fd5b50610495610b03366004612bf0565b612175565b348015610b13575f80fd5b506103f760125481565b348015610b28575f80fd5b50610466610b373660046130c7565b6001600160a01b039182165f90815260076020908152604080832093909416825291909152205460ff1690565b348015610b6f575f80fd5b50610495610b7e366004612bd5565b612182565b348015610b8e575f80fd5b50610495610b9d366004612bf0565b6121bf565b348015610bad575f80fd5b50610495610bbc3660046130f3565b6121cc565b5f610bcb826122c1565b92915050565b610bd96122f5565b610be382826122fd565b5050565b606060028054610bf69061314c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c229061314c565b8015610c6d5780601f10610c4457610100808354040283529160200191610c6d565b820191905f5260205f20905b815481529060010190602001808311610c5057829003601f168201915b5050505050905090565b5f601454600103610ca7576001600160a01b0382165f90815260186020526040902054600f54610bcb9190613198565b601454600203610cd6576001600160a01b0382165f90815260196020526040902054600e54610bcb9190613198565b505f919050565b5f610ce782612352565b610cfb57610cfb6333d1c03960e21b61239c565b505f908152600660205260409020546001600160a01b031690565b610be3828260016123a4565b610d2a612445565b601055565b610d37612445565b601754610100900460ff1615610d685760405162461bcd60e51b8152600401610d5f906131ab565b60405180910390fd5b6016610be38282613226565b600a545f906001600160a01b031615610dfe57600a5460405163050bf71960e31b81526001600160a01b038681166004830152858116602483015284811660448301529091169063285fb8c8906064015f6040518083038186803b158015610dda575f80fd5b505afa925050508015610deb575060015b610df657505f610e02565b506001610e02565b5060015b9392505050565b5f610e1382612472565b6001600160a01b039485169490915081168414610e3957610e3962a1148160e81b61239c565b5f8281526006602052604090208054338082146001600160a01b03881690911417610e7c57610e688633610b37565b610e7c57610e7c632ce44b5f60e11b61239c565b610e89868686600161250b565b8015610e93575f82555b6001600160a01b038681165f9081526005602052604080822080545f19019055918716808252919020805460010190554260a01b17600160e11b175f85815260046020526040812091909155600160e11b84169003610f1f57600184015f818152600460205260408120549003610f1d575f548114610f1d575f8181526004602052604090208490555b505b6001600160a01b0385168481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4805f03610f6757610f67633a954ecd60e21b61239c565b610f748787876001612538565b50505050505050565b610f85612445565b6001601455565b5f828152600c6020526040812080548291906001600160a01b03811690600160a01b90046001600160601b031681610fdf575050600b546001600160a01b03811690600160a01b90046001600160601b03165b5f612710610ff66001600160601b038416896132e1565b61100091906132f8565b9295509193505050505b9250929050565b611019612445565b478061105e5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610d5f565b808211156110a15760405162461bcd60e51b815260206004820152601060248201526f6e6f7420656e6f7567682066756e647360801b6044820152606401610d5f565b604051339083156108fc029084905f818181858888f193505050501580156110cb573d5f803e3d5ffd5b505050565b600a545f906001600160a01b031615610cd657600a54604051635caaa2a960e11b81523060048201526001600160a01b039091169063d72dde5e90829063b955455290602401606060405180830381865afa158015611131573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111559190613317565b602001516040516001600160e01b031960e084901b1681526001600160781b0390911660048201526001600160a01b03851660248201526044015b602060405180830381865afa1580156111ab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bcb9190613389565b6111d7612445565b600f55565b6110cb83838360405180602001604052805f815250611a30565b600a546060906001600160a01b0316156112ee57600a54604051635caaa2a960e11b81523060048201526001600160a01b0390911690633fe5df9990829063b955455290602401606060405180830381865afa158015611258573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127c9190613317565b602001516040516001600160e01b031960e084901b1681526001600160781b0390911660048201526024015b5f60405180830381865afa1580156112c2573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112e991908101906133a4565b905090565b50604080515f81526020810190915290565b611308612445565b601754610100900460ff16156113305760405162461bcd60e51b8152600401610d5f906131ab565b6015610be38282613226565b6113446122f5565b6110cb83838361255e565b6040516bffffffffffffffffffffffff19606085901b1660208201525f9081906034016040516020818303038152906040528051906020012090506113ca8484808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050600d5491508490506125b7565b95945050505050565b6113db612445565b601255565b6113e86122f5565b5f6113fb600a546001600160a01b031690565b90506001600160a01b03811661142457604051631cffe3dd60e11b815260040160405180910390fd5b604051630368065360e61b81526001600160a01b0382169063da0194c0906114529030908890600401613458565b5f604051808303815f87803b158015611469575f80fd5b505af115801561147b573d5f803e3d5ffd5b5050604051631182550160e11b81526001600160a01b0384169250632304aa0291506114ad9030908790600401613475565b5f604051808303815f87803b1580156114c4575f80fd5b505af11580156114d6573d5f803e3d5ffd5b505060405163235d10c560e21b81526001600160a01b0384169250638d74431491506115089030908690600401613475565b5f604051808303815f87803b15801561151f575f80fd5b505af1158015611531573d5f803e3d5ffd5b5050505050505050565b5f610bcb82612472565b601580546115529061314c565b80601f016020809104026020016040519081016040528092919081815260200182805461157e9061314c565b80156115c95780601f106115a0576101008083540402835291602001916115c9565b820191905f5260205f20905b8154815290600101906020018083116115ac57829003601f168201915b505050505081565b6115d96122f5565b6115f471721c310194ccfc01e523fc93c9cccfa2a0ac611911565b604051630368065360e61b815271721c310194ccfc01e523fc93c9cccfa2a0ac9063da0194c09061162c903090600190600401613458565b5f604051808303815f87803b158015611643575f80fd5b505af1158015611655573d5f803e3d5ffd5b5050604051631182550160e11b815271721c310194ccfc01e523fc93c9cccfa2a0ac9250632304aa029150611691903090600190600401613475565b5f604051808303815f87803b1580156116a8575f80fd5b505af11580156116ba573d5f803e3d5ffd5b50505050565b5f6001600160a01b0382166116df576116df6323d3ad8160e21b61239c565b506001600160a01b03165f9081526005602052604090205467ffffffffffffffff1690565b61170c612445565b6117155f6125cc565b565b61171f612445565b6002601455565b61172e612445565b600d55565b61173b612445565b5f601455565b611749612445565b478061178e5760405162461bcd60e51b81526020600482015260146024820152734e6f2066756e647320746f20776974686472617760601b6044820152606401610d5f565b604051339082156108fc029083905f818181858888f19350505050158015610be3573d5f803e3d5ffd5b601680546115529061314c565b606060038054610bf69061314c565b600a545f906001600160a01b031615610cd657600a54604051635caaa2a960e11b81523060048201526001600160a01b0390911690639445f53090829063b955455290602401606060405180830381865afa158015611835573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118599190613317565b60409081015190516001600160e01b031960e084901b1681526001600160781b0390911660048201526001600160a01b0385166024820152604401611190565b335f8181526007602090815260408083206001600160a01b0387168085529252909120805460ff1916841515179055906001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611905911515815260200190565b60405180910390a35050565b6119196122f5565b5f6001600160a01b0382163b15611992576040516301ffc9a760e01b81525f60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa92505050801561198a575060408051601f3d908101601f1916820190925261198791810190613389565b60015b156119925790505b6001600160a01b038216158015906119a8575080155b156119c6576040516332483afb60e01b815260040160405180910390fd5b600a54604080516001600160a01b03928316815291841660208301527fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac910160405180910390a150600a80546001600160a01b0319166001600160a01b0392909216919091179055565b611a3b848484610e09565b6001600160a01b0383163b156116ba57611a578484848461261d565b6116ba576116ba6368d2bf6b60e11b61239c565b333214611ac45760405162461bcd60e51b815260206004820152602160248201527f46756e6374696f6e206d7573742062652063616c6c656420627920616e20454f6044820152604160f81b6064820152608401610d5f565b6001831015611ae65760405163011674e560e71b815260040160405180910390fd5b60105483611af96001545f54035f190190565b611b039190613497565b1115611b22576040516376592c6f60e01b815260040160405180910390fd5b6014545f03611b44576040516306d39fcd60e41b815260040160405180910390fd5b601454600103611ccc57335f8181526018602052604090205490611b6990848461134f565b611bb55760405162461bcd60e51b815260206004820152601760248201527f55736572206973206e6f742077686974656c69737465640000000000000000006044820152606401610d5f565b60115484611bc86001545f54035f190190565b611bd29190613497565b1115611c195760405162461bcd60e51b8152602060048201526016602482015275139bdd08115b9bdd59da08151bdad95b9cc81319599d60521b6044820152606401610d5f565b600f54611c268583613497565b1115611c745760405162461bcd60e51b815260206004820152601c60248201527f4d6178204e4654207065722061646472657373206578636565646564000000006044820152606401610d5f565b83601254611c8291906132e1565b341015611cc65760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b6044820152606401610d5f565b50611d94565b601454600203611d9457335f90815260196020526040902054600e54611cf28583613497565b1115611d405760405162461bcd60e51b815260206004820152601c60248201527f4d6178204e4654207065722061646472657373206578636565646564000000006044820152606401610d5f565b83601354611d4e91906132e1565b341015611d925760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b6044820152606401610d5f565b505b611d9e33846126fc565b601454600103611dd157335f9081526018602052604081208054859290611dc6908490613497565b909155506110cb9050565b6014546002036110cb57335f9081526019602052604081208054859290611df9908490613497565b9091555050505050565b611e0b612445565b60105482611e1e6001545f54035f190190565b611e289190613497565b1115611e47576040516376592c6f60e01b815260040160405180910390fd5b610be381836126fc565b604080516060810182525f8082526020820181905291810191909152600a546001600160a01b031615611ee857600a54604051635caaa2a960e11b81523060048201526001600160a01b039091169063b955455290602401606060405180830381865afa158015611ec4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112e99190613317565b50604080516060810182525f808252602082018190529181019190915290565b6060611f1382612352565b611f5f5760405162461bcd60e51b815260206004820152601f60248201527f55524920717565727920666f72206e6f6e6578697374656e7420746f6b656e006044820152606401610d5f565b60175460ff1615155f03611ffd5760168054611f7a9061314c565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa69061314c565b8015611ff15780601f10611fc857610100808354040283529160200191611ff1565b820191905f5260205f20905b815481529060010190602001808311611fd457829003601f168201915b50505050509050919050565b5f6120066127cb565b90505f8151116120245760405180602001604052805f815250610e02565b8061202e846127da565b60405160200161203f9291906134c1565b6040516020818303038152906040529392505050565b600a546060906001600160a01b0316156112ee57600a54604051635caaa2a960e11b81523060048201526001600160a01b03909116906317e94a6c90829063b955455290602401606060405180830381865afa1580156120b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120db9190613317565b60409081015190516001600160e01b031960e084901b1681526001600160781b0390911660048201526024016112a8565b612114612445565b6017805461ff001916610100179055565b61212d612445565b601355565b61213a612445565b601754610100900460ff16156121625760405162461bcd60e51b8152600401610d5f906131ab565b6017805460ff1916911515919091179055565b61217d612445565b600e55565b61218a612445565b6001600160a01b0381166121b357604051631e4fbdf760e01b81525f6004820152602401610d5f565b6121bc816125cc565b50565b6121c7612445565b601155565b6121d46122f5565b6121dd84611911565b604051630368065360e61b81526001600160a01b0385169063da0194c09061220b9030908790600401613458565b5f604051808303815f87803b158015612222575f80fd5b505af1158015612234573d5f803e3d5ffd5b5050604051631182550160e11b81526001600160a01b0387169250632304aa0291506122669030908690600401613475565b5f604051808303815f87803b15801561227d575f80fd5b505af115801561228f573d5f803e3d5ffd5b505060405163235d10c560e21b81526001600160a01b0387169250638d74431491506115089030908590600401613475565b5f6001600160e01b0319821663152a902d60e11b1480610bcb57506301ffc9a760e01b6001600160e01b0319831614610bcb565b611715612445565b612307828261281d565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b5f81600111612397575f54821015612397575f5b505f828152600460205260408120549081900361238d57612386836134eb565b9250612366565b600160e01b161590505b919050565b805f5260045ffd5b5f6123ae8361153b565b90508180156123c65750336001600160a01b03821614155b156123e9576123d58133610b37565b6123e9576123e96367d9dca160e11b61239c565b5f8381526006602052604080822080546001600160a01b0319166001600160a01b0388811691821790925591518693918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b6009546001600160a01b031633146117155760405163118cdaa760e01b8152336004820152602401610d5f565b5f816001116124fb57505f81815260046020526040902054805f036124e9575f5482106124a9576124a9636f96cda160e11b61239c565b5b505f19015f8181526004602052604090205480156124aa57600160e01b81165f036124d457919050565b6124e4636f96cda160e11b61239c565b6124aa565b600160e01b81165f036124fb57919050565b612397636f96cda160e11b61239c565b5f5b818110156125315761252985856125248487613497565b6128bf565b60010161250d565b5050505050565b5f5b818110156125315761255685856125518487613497565b612915565b60010161253a565b61256983838361295c565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c9060200160405180910390a3505050565b5f826125c38584612a1c565b14949350505050565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b604051630a85bd0160e11b81525f906001600160a01b0385169063150b7a0290612651903390899088908890600401613500565b6020604051808303815f875af192505050801561268b575060408051601f3d908101601f191682019092526126889181019061353c565b60015b6126de573d8080156126b8576040519150601f19603f3d011682016040523d82523d5f602084013e6126bd565b606091505b5080515f036126d6576126d66368d2bf6b60e11b61239c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b5f8054908290036127175761271763b562e8dd60e01b61239c565b6127235f84838561250b565b5f8181526004602090815260408083206001600160a01b0387164260a01b6001881460e11b1781179091558084526005909252822080546801000000000000000186020190559081900361278057612780622e076360e81b61239c565b818301825b80835f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a481816001019150810361278557505f9081556110cb9150848385612538565b606060158054610bf69061314c565b606060a06040510180604052602081039150505f815280825b600183039250600a81066030018353600a9004806127f35750819003601f19909101908152919050565b6127106001600160601b03821681101561285c57604051636f483d0960e01b81526001600160601b038316600482015260248101829052604401610d5f565b6001600160a01b03831661288557604051635b6cc80560e11b81525f6004820152602401610d5f565b50604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600b55565b6001600160a01b0383811615908316158180156128d95750805b156128f757604051635cbd944160e01b815260040160405180910390fd5b8115612903575b612531565b806128fe576125313386868634612a5e565b6001600160a01b03838116159083161581801561292f5750805b1561294d57604051635cbd944160e01b815260040160405180910390fd5b816128fe57806128fe57612531565b6127106001600160601b0382168110156129a25760405163dfd1fc1b60e01b8152600481018590526001600160601b038316602482015260448101829052606401610d5f565b6001600160a01b0383166129d257604051634b4f842960e11b8152600481018590525f6024820152604401610d5f565b506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182525f968752600c90529190942093519051909116600160a01b029116179055565b5f81815b8451811015612a5657612a4c82868381518110612a3f57612a3f613557565b6020026020010151612adf565b9150600101612a20565b509392505050565b600a546001600160a01b03161561253157600a5460405163050bf71960e31b81526001600160a01b038781166004830152868116602483015285811660448301529091169063285fb8c8906064015f6040518083038186803b158015612ac2575f80fd5b505afa158015612ad4573d5f803e3d5ffd5b505050505050505050565b5f818310612af9575f828152602084905260409020610e02565b505f9182526020526040902090565b6001600160e01b0319811681146121bc575f80fd5b5f60208284031215612b2d575f80fd5b8135610e0281612b08565b6001600160a01b03811681146121bc575f80fd5b80356001600160601b0381168114612397575f80fd5b5f8060408385031215612b73575f80fd5b8235612b7e81612b38565b9150612b8c60208401612b4c565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e026020830184612b95565b5f60208284031215612be5575f80fd5b8135610e0281612b38565b5f60208284031215612c00575f80fd5b5035919050565b5f8060408385031215612c18575f80fd5b8235612c2381612b38565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612c6e57612c6e612c31565b604052919050565b5f8067ffffffffffffffff841115612c9057612c90612c31565b50601f8301601f1916602001612ca581612c45565b915050828152838383011115612cb9575f80fd5b828260208301375f602084830101529392505050565b5f60208284031215612cdf575f80fd5b813567ffffffffffffffff811115612cf5575f80fd5b8201601f81018413612d05575f80fd5b6126f484823560208401612c76565b5f805f60608486031215612d26575f80fd5b8335612d3181612b38565b92506020840135612d4181612b38565b91506040840135612d5181612b38565b809150509250925092565b60078110612d7857634e487b7160e01b5f52602160045260245ffd5b9052565b60208101610bcb8284612d5c565b5f805f60608486031215612d9c575f80fd5b8335612da781612b38565b92506020840135612db781612b38565b929592945050506040919091013590565b5f8060408385031215612dd9575f80fd5b50508035926020909101359150565b602080825282518282018190525f918401906040840190835b81811015612e285783516001600160a01b0316835260209384019390920191600101612e01565b509095945050505050565b5f805f60608486031215612e45575f80fd5b833592506020840135612e5781612b38565b9150612e6560408501612b4c565b90509250925092565b5f8083601f840112612e7e575f80fd5b50813567ffffffffffffffff811115612e95575f80fd5b6020830191508360208260051b850101111561100a575f80fd5b5f805f60408486031215612ec1575f80fd5b8335612ecc81612b38565b9250602084013567ffffffffffffffff811115612ee7575f80fd5b612ef386828701612e6e565b9497909650939450505050565b600781106121bc575f80fd5b6001600160781b03811681146121bc575f80fd5b5f805f60608486031215612f32575f80fd5b8335612f3d81612f00565b92506020840135612f4d81612f0c565b91506040840135612d5181612f0c565b80151581146121bc575f80fd5b5f8060408385031215612f7b575f80fd5b8235612f8681612b38565b91506020830135612f9681612f5d565b809150509250929050565b5f805f8060808587031215612fb4575f80fd5b8435612fbf81612b38565b93506020850135612fcf81612b38565b925060408501359150606085013567ffffffffffffffff811115612ff1575f80fd5b8501601f81018713613001575f80fd5b61301087823560208401612c76565b91505092959194509250565b5f805f6040848603121561302e575f80fd5b83359250602084013567ffffffffffffffff811115612ee7575f80fd5b5f806040838503121561305c575f80fd5b823591506020830135612f9681612b38565b5f606082019050613080828451612d5c565b6001600160781b0360208401511660208301526001600160781b03604084015116604083015292915050565b5f602082840312156130bc575f80fd5b8135610e0281612f5d565b5f80604083850312156130d8575f80fd5b82356130e381612b38565b91506020830135612f9681612b38565b5f805f8060808587031215613106575f80fd5b843561311181612b38565b9350602085013561312181612f00565b9250604085013561313181612f0c565b9150606085013561314181612f0c565b939692955090935050565b600181811c9082168061316057607f821691505b60208210810361317e57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610bcb57610bcb613184565b6020808252601b908201527f436f6e7472616374206d657461646174612069732066726f7a656e0000000000604082015260600190565b601f8211156110cb57805f5260205f20601f840160051c810160208510156132075750805b601f840160051c820191505b81811015612531575f8155600101613213565b815167ffffffffffffffff81111561324057613240612c31565b6132548161324e845461314c565b846131e2565b6020601f821160018114613286575f831561326f5750848201515b5f19600385901b1c1916600184901b178455612531565b5f84815260208120601f198516915b828110156132b55787850151825560209485019460019092019101613295565b50848210156132d257868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b8082028115828204841417610bcb57610bcb613184565b5f8261331257634e487b7160e01b5f52601260045260245ffd5b500490565b5f6060828403128015613328575f80fd5b506040516060810167ffffffffffffffff8111828210171561334c5761334c612c31565b604052825161335a81612f00565b8152602083015161336a81612f0c565b6020820152604083015161337d81612f0c565b60408201529392505050565b5f60208284031215613399575f80fd5b8151610e0281612f5d565b5f602082840312156133b4575f80fd5b815167ffffffffffffffff8111156133ca575f80fd5b8201601f810184136133da575f80fd5b805167ffffffffffffffff8111156133f4576133f4612c31565b8060051b61340460208201612c45565b9182526020818401810192908101908784111561341f575f80fd5b6020850194505b8385101561344d578451925061343b83612b38565b82825260209485019490910190613426565b979650505050505050565b6001600160a01b038316815260408101610e026020830184612d5c565b6001600160a01b039290921682526001600160781b0316602082015260400190565b80820180821115610bcb57610bcb613184565b5f81518060208401855e5f93019283525090919050565b5f6134d56134cf83866134aa565b846134aa565b64173539b7b760d91b8152600501949350505050565b5f816134f9576134f9613184565b505f190190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061353290830184612b95565b9695505050505050565b5f6020828403121561354c575f80fd5b8151610e0281612b08565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220dd0738d8066e9ad5f833c3ac142499d0d134076f3a694674f62b4bbf7b3ff43e64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009364521aacba93f4309bd933254459f2d04f742e0000000000000000000000009364521aacba93f4309bd933254459f2d04f742e000000000000000000000000000000000000000000000000000000000000012c
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x9364521aaCBA93f4309Bd933254459F2D04F742e
Arg [1] : royaltyReceiver_ (address): 0x9364521aaCBA93f4309Bd933254459F2D04F742e
Arg [2] : royaltyFeeNumerator_ (uint96): 300
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000009364521aacba93f4309bd933254459f2d04f742e
Arg [1] : 0000000000000000000000009364521aacba93f4309bd933254459f2d04f742e
Arg [2] : 000000000000000000000000000000000000000000000000000000000000012c
Deployed Bytecode Sourcemap
327:10378:25:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;538:33;;;;;;;;;;;;;;;;;;;160:25:26;;;148:2;133:18;538:33:25;;;;;;;;1928:104:12;;;;;;;;;;;;1989:42;1928:104;;;;;-1:-1:-1;;;;;360:32:26;;;342:51;;330:2;315:18;1928:104:12;196:203:26;10528:172:25;;;;;;;;;;-1:-1:-1;10528:172:25;;;;;:::i;:::-;;:::i;:::-;;;955:14:26;;948:22;930:41;;918:2;903:18;10528:172:25;790:187:26;9894:176:25;;;;;;;;;;-1:-1:-1;9894:176:25;;;;;:::i;:::-;;:::i;:::-;;851:18;;;;;;;;;;-1:-1:-1;851:18:25;;;;;;;;;;;11881:100:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4305:314:25:-;;;;;;;;;;-1:-1:-1;4305:314:25;;;;;:::i;:::-;;:::i;19121:227:13:-;;;;;;;;;;-1:-1:-1;19121:227:13;;;;;:::i;:::-;;:::i;18838:124::-;;;;;;:::i;:::-;;:::i;6454:137:12:-;;;;;;;;;;-1:-1:-1;6566:17:12;;-1:-1:-1;;;;;6566:17:12;6454:137;;724:31:25;;;;;;;;;;;;;;;;615:29;;;;;;;;;;;;;;;;878:57;;;;;;;;;;-1:-1:-1;878:57:25;;;;;:::i;:::-;;;;;;;;;;;;;;6831:102;;;;;;;;;;-1:-1:-1;6831:102:25;;;;;:::i;:::-;;:::i;8404:144::-;;;;;;;;;;-1:-1:-1;8404:144:25;;;;;:::i;:::-;;:::i;7083:573:13:-;;;;;;;;;;;;5225:1:25;7527:12:13;7144:14;7511:13;:28;-1:-1:-1;;7511:46:13;;7083:573;10238:387:12;;;;;;;;;;-1:-1:-1;10238:387:12;;;;;:::i;:::-;;:::i;2039:99::-;;;;;;;;;;;;2112:26;2039:99;;;;;;;;;:::i;23393:3523:13:-;;;;;;:::i;:::-;;:::i;8792:84:25:-;;;;;;;;;;;;;:::i;2379:657:3:-;;;;;;;;;;-1:-1:-1;2379:657:3;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6808:32:26;;;6790:51;;6872:2;6857:18;;6850:34;;;;6763:18;2379:657:3;6616:274:26;9149:273:25;;;;;;;;;;-1:-1:-1;9149:273:25;;;;;:::i;:::-;;:::i;8583:357:12:-;;;;;;;;;;-1:-1:-1;8583:357:12;;;;;:::i;:::-;;:::i;467:25:25:-;;;;;;;;;;;;;;;;6610:104;;;;;;;;;;-1:-1:-1;6610:104:25;;;;;:::i;:::-;;:::i;27012:193:13:-;;;;;;:::i;:::-;;:::i;7470:358:12:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;824:20:25:-;;;;;;;;;;-1:-1:-1;824:20:25;;;;;;;;8143:120;;;;;;;;;;-1:-1:-1;8143:120:25;;;;;:::i;:::-;;:::i;10269:198::-;;;;;;;;;;-1:-1:-1;10269:198:25;;;;;:::i;:::-;;:::i;3934:266::-;;;;;;;;;;-1:-1:-1;3934:266:25;;;;;:::i;:::-;;:::i;2145:66:12:-;;;;;;;;;;;;2209:1;2145:66;;;;;-1:-1:-1;;;;;9276:45:26;;;9258:64;;9246:2;9231:18;2145:66:12;9112:216:26;7519:106:25;;;;;;;;;;-1:-1:-1;7519:106:25;;;;;:::i;:::-;;:::i;4194:727:12:-;;;;;;;;;;-1:-1:-1;4194:727:12;;;;;:::i;:::-;;:::i;13283:152:13:-;;;;;;;;;;-1:-1:-1;13283:152:13;;;;;:::i;:::-;;:::i;762:21:25:-;;;;;;;;;;;;;:::i;2585:464:12:-;;;;;;;;;;;;;:::i;8807:242:13:-;;;;;;;;;;-1:-1:-1;8807:242:13;;;;;:::i;:::-;;:::i;2293:101:0:-;;;;;;;;;;;;;:::i;8951:75:25:-;;;;;;;;;;;;;:::i;6119:106::-;;;;;;;;;;-1:-1:-1;6119:106:25;;;;;:::i;:::-;;:::i;8650:71::-;;;;;;;;;;;;;:::i;9509:203::-;;;;;;;;;;;;;:::i;1638:85:0:-;;;;;;;;;;-1:-1:-1;1710:6:0;;-1:-1:-1;;;;;1710:6:0;1638:85;;790:27:25;;;;;;;;;;;;;:::i;12057:104:13:-;;;;;;;;;;;;;:::i;9112:378:12:-;;;;;;;;;;-1:-1:-1;9112:378:12;;;;;:::i;:::-;;:::i;19688:234:13:-;;;;;;;;;;-1:-1:-1;19688:234:13;;;;;:::i;:::-;;:::i;5521:818:12:-;;;;;;;;;;-1:-1:-1;5521:818:12;;;;;:::i;:::-;;:::i;942:48:25:-;;;;;;;;;;-1:-1:-1;942:48:25;;;;;:::i;:::-;;;;;;;;;;;;;;27803:416:13;;;;;;:::i;:::-;;:::i;1968:1881:25:-;;;;;;:::i;:::-;;:::i;4847:231::-;;;;;;;;;;-1:-1:-1;4847:231:25;;;;;:::i;:::-;;:::i;499:32::-;;;;;;;;;;;;;;;;6808:455:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;5538:422:25:-;;;;;;;;;;-1:-1:-1;5538:422:25;;;;;:::i;:::-;;:::i;690:27::-;;;;;;;;;;;;;;;;8038:379:12;;;;;;;;;;;;;:::i;7935:77:25:-;;;;;;;;;;;;;:::i;578:30::-;;;;;;;;;;;;;;;;7288:96;;;;;;;;;;-1:-1:-1;7288:96:25;;;;;:::i;:::-;;:::i;7744:102::-;;;;;;;;;;-1:-1:-1;7744:102:25;;;;;:::i;:::-;;:::i;6358:100::-;;;;;;;;;;-1:-1:-1;6358:100:25;;;;;:::i;:::-;;:::i;651:32::-;;;;;;;;;;;;;;;;20079:164:13;;;;;;;;;;-1:-1:-1;20079:164:13;;;;;:::i;:::-;-1:-1:-1;;;;;20200:25:13;;;20176:4;20200:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;20079:164;2543:215:0;;;;;;;;;;-1:-1:-1;2543:215:0;;;;;:::i;:::-;;:::i;7072:100:25:-;;;;;;;;;;-1:-1:-1;7072:100:25;;;;;:::i;:::-;;:::i;3252:749:12:-;;;;;;;;;;-1:-1:-1;3252:749:12;;;;;:::i;:::-;;:::i;10528:172:25:-;10632:4;10656:36;10680:11;10656:23;:36::i;:::-;10649:43;10528:172;-1:-1:-1;;10528:172:25:o;9894:176::-;9978:31;:29;:31::i;:::-;10020:42;10039:8;10049:12;10020:18;:42::i;:::-;9894:176;;:::o;11881:100:13:-;11935:13;11968:5;11961:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11881:100;:::o;4305:314:25:-;4372:7;4396:12;;4412:1;4396:17;4392:201;;-1:-1:-1;;;;;4454:29:25;;;;;;:22;:29;;;;;;4437:14;;:46;;4454:29;4437:46;:::i;4392:201::-;4505:12;;4521:1;4505:17;4501:92;;-1:-1:-1;;;;;4561:20:25;;;;;;:13;:20;;;;;;4546:12;;:35;;4561:20;4546:35;:::i;4501:92::-;-1:-1:-1;4610:1:25;;4305:314;-1:-1:-1;4305:314:25:o;19121:227:13:-;19197:7;19222:16;19230:7;19222;:16::i;:::-;19217:73;;19240:50;-1:-1:-1;;;19240:7:13;:50::i;:::-;-1:-1:-1;19310:24:13;;;;:15;:24;;;;;:30;-1:-1:-1;;;;;19310:30:13;;19121:227::o;18838:124::-;18927:27;18936:2;18940:7;18949:4;18927:8;:27::i;6831:102:25:-;1531:13:0;:11;:13::i;:::-;6903:9:25::1;:22:::0;6831:102::o;8404:144::-;1531:13:0;:11;:13::i;:::-;1184:6:25::1;::::0;::::1;::::0;::::1;;;1183:7;1175:47;;;;-1:-1:-1::0;;;1175:47:25::1;;;;;;;:::i;:::-;;;;;;;;;8507:13:::2;:33;8523:17:::0;8507:13;:33:::2;:::i;10238:387:12:-:0;10366:17;;10337:4;;-1:-1:-1;;;;;10366:17:12;10358:40;10354:242;;10419:17;;:65;;-1:-1:-1;;;10419:65:12;;-1:-1:-1;;;;;17885:32:26;;;10419:65:12;;;17867:51:26;17954:32;;;17934:18;;;17927:60;18023:32;;;18003:18;;;17996:60;10419:17:12;;;;:47;;17840:18:26;;10419:65:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10415:170;;-1:-1:-1;10564:5:12;10557:12;;10415:170;-1:-1:-1;10511:4:12;10504:11;;10415:170;-1:-1:-1;10613:4:12;10238:387;;;;;;:::o;23393:3523:13:-;23535:27;23565;23584:7;23565:18;:27::i;:::-;-1:-1:-1;;;;;23720:22:13;;;;23535:57;;-1:-1:-1;23780:45:13;;;;23776:95;;23827:44;-1:-1:-1;;;23827:7:13;:44::i;:::-;23885:27;22501:24;;;:15;:24;;;;;22729:26;;735:10:5;22126:30:13;;;-1:-1:-1;;;;;21819:28:13;;22104:20;;;22101:56;24071:189;;24164:43;24181:4;735:10:5;24187:19:13;7470:358:12;24164:43:13;24159:101;;24209:51;-1:-1:-1;;;24209:7:13;:51::i;:::-;24273:43;24295:4;24301:2;24305:7;24314:1;24273:21;:43::i;:::-;24409:15;24406:160;;;24549:1;24528:19;24521:30;24406:160;-1:-1:-1;;;;;24946:24:13;;;;;;;:18;:24;;;;;;24944:26;;-1:-1:-1;;24944:26:13;;;25015:22;;;;;;;;;25013:24;;-1:-1:-1;25013:24:13;;;17940:11;17915:23;17911:41;17898:63;-1:-1:-1;;;17898:63:13;25308:26;;;;:17;:26;;;;;:175;;;;-1:-1:-1;;;25603:47:13;;:52;;25599:627;;25708:1;25698:11;;25676:19;25831:30;;;:17;:30;;;;;;:35;;25827:384;;25969:13;;25954:11;:28;25950:242;;26116:30;;;;:17;:30;;;;;:52;;;25950:242;25657:569;25599:627;-1:-1:-1;;;;;26358:20:13;;26738:7;26358:20;26668:4;26610:25;26339:16;;26475:299;26799:8;26811:1;26799:13;26795:58;;26814:39;-1:-1:-1;;;26814:7:13;:39::i;:::-;26866:42;26887:4;26893:2;26897:7;26906:1;26866:20;:42::i;:::-;23524:3392;;;;23393:3523;;;:::o;8792:84:25:-;1531:13:0;:11;:13::i;:::-;8867:1:25::1;8852:12;:16:::0;8792:84::o;2379:657:3:-;2487:16;2566:26;;;:17;:26;;;;;2628:21;;2487:16;;2566:26;-1:-1:-1;;;;;2628:21:3;;;-1:-1:-1;;;2684:28:3;;-1:-1:-1;;;;;2684:28:3;2628:21;2723:173;;-1:-1:-1;;2790:19:3;:28;-1:-1:-1;;;;;2790:28:3;;;-1:-1:-1;;;2850:35:3;;-1:-1:-1;;;;;2850:35:3;2723:173;2906:21;3394:5;2931:27;-1:-1:-1;;;;;2931:27:3;;:9;:27;:::i;:::-;2930:49;;;;:::i;:::-;2998:15;;-1:-1:-1;2906:73:3;;-1:-1:-1;;;;2379:657:3;;;;;;:::o;9149:273:25:-;1531:13:0;:11;:13::i;:::-;9232:21:25::1;9272:11:::0;9264:44:::1;;;::::0;-1:-1:-1;;;9264:44:25;;18664:2:26;9264:44:25::1;::::0;::::1;18646:21:26::0;18703:2;18683:18;;;18676:30;-1:-1:-1;;;18722:18:26;;;18715:50;18782:18;;9264:44:25::1;18462:344:26::0;9264:44:25::1;9338:7;9327;:18;;9319:47;;;::::0;-1:-1:-1;;;9319:47:25;;19013:2:26;9319:47:25::1;::::0;::::1;18995:21:26::0;19052:2;19032:18;;;19025:30;-1:-1:-1;;;19071:18:26;;;19064:46;19127:18;;9319:47:25::1;18811:340:26::0;9319:47:25::1;9377:37;::::0;9385:10:::1;::::0;9377:37;::::1;;;::::0;9406:7;;9377:37:::1;::::0;;;9406:7;9385:10;9377:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;9203:219;9149:273:::0;:::o;8583:357:12:-;8691:17;;8662:4;;-1:-1:-1;;;;;8691:17:12;8683:40;8679:229;;8747:17;;8805:60;;-1:-1:-1;;;8805:60:12;;8859:4;8805:60;;;342:51:26;-1:-1:-1;;;;;8747:17:12;;;;:39;;:17;;8805:45;;315:18:26;;8805:60:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;8747:149;;-1:-1:-1;;;;;;8747:149:12;;;;;;;-1:-1:-1;;;;;20220:45:26;;;8747:149:12;;;20202:64:26;-1:-1:-1;;;;;20302:32:26;;20282:18;;;20275:60;20175:18;;8747:149:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;6610:104:25:-;1531:13:0;:11;:13::i;:::-;6683:14:25::1;:23:::0;6610:104::o;27012:193:13:-;27158:39;27175:4;27181:2;27185:7;27158:39;;;;;;;;;;;;:16;:39::i;7470:358:12:-;7576:17;;7535:16;;-1:-1:-1;;;;;7576:17:12;7568:40;7564:221;;7632:17;;7692:60;;-1:-1:-1;;;7692:60:12;;7746:4;7692:60;;;342:51:26;-1:-1:-1;;;;;7632:17:12;;;;:41;;:17;;7692:45;;315:18:26;;7692:60:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:80;;;7632:141;;-1:-1:-1;;;;;;7632:141:12;;;;;;;-1:-1:-1;;;;;9276:45:26;;;7632:141:12;;;9258:64:26;9231:18;;7632:141:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7632:141:12;;;;;;;;;;;;:::i;:::-;7625:148;;7470:358;:::o;7564:221::-;-1:-1:-1;7804:16:12;;;7818:1;7804:16;;;;;;;;;7470:358::o;8143:120:25:-;1531:13:0;:11;:13::i;:::-;1184:6:25::1;::::0;::::1;::::0;::::1;;;1183:7;1175:47;;;;-1:-1:-1::0;;;1175:47:25::1;;;;;;;:::i;:::-;8234:7:::2;:21;8244:11:::0;8234:7;:21:::2;:::i;10269:198::-:0;10368:31;:29;:31::i;:::-;10410:49;10427:7;10436:8;10446:12;10410:16;:49::i;3934:266::-;4100:23;;-1:-1:-1;;21751:2:26;21747:15;;;21743:53;4100:23:25;;;21731:66:26;4053:4:25;;;;21813:12:26;;4100:23:25;;;;;;;;;;;;4090:34;;;;;;4075:49;;4142:50;4161:12;;4142:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4175:10:25;;;-1:-1:-1;4187:4:25;;-1:-1:-1;4142:18:25;:50::i;:::-;4135:57;3934:266;-1:-1:-1;;;;;3934:266:25:o;7519:106::-;1531:13:0;:11;:13::i;:::-;7593::25::1;:24:::0;7519:106::o;4194:727:12:-;4383:31;:29;:31::i;:::-;4427:40;4470:22;6566:17;;-1:-1:-1;;;;;6566:17:12;;6454:137;4470:22;4427:65;-1:-1:-1;;;;;;4507:32:12;;4503:117;;4563:45;;-1:-1:-1;;;4563:45:12;;;;;;;;;;;4503:117;4632:68;;-1:-1:-1;;;4632:68:12;;-1:-1:-1;;;;;4632:46:12;;;;;:68;;4687:4;;4694:5;;4632:68;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4711:78:12;;-1:-1:-1;;;4711:78:12;;-1:-1:-1;;;;;4711:42:12;;;-1:-1:-1;4711:42:12;;-1:-1:-1;4711:78:12;;4762:4;;4769:19;;4711:78;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4800:113:12;;-1:-1:-1;;;4800:113:12;;-1:-1:-1;;;;;4800:59:12;;;-1:-1:-1;4800:59:12;;-1:-1:-1;4800:113:12;;4868:4;;4875:37;;4800:113;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4372:549;4194:727;;;:::o;13283:152:13:-;13355:7;13398:27;13417:7;13398:18;:27::i;762:21:25:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2585:464:12:-;2649:31;:29;:31::i;:::-;2691:48;1989:42;2691:20;:48::i;:::-;2750:143;;-1:-1:-1;;;2750:143:12;;1989:42;;2750:95;;:143;;2854:4;;2112:26;;2750:143;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2904:137:12;;-1:-1:-1;;;2904:137:12;;1989:42;;-1:-1:-1;2904:91:12;;-1:-1:-1;2904:137:12;;3004:4;;2209:1;;2904:137;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2585:464::o;8807:242:13:-;8879:7;-1:-1:-1;;;;;8903:19:13;;8899:69;;8924:44;-1:-1:-1;;;8924:7:13;:44::i;:::-;-1:-1:-1;;;;;;8986:25:13;;;;;:18;:25;;;;;;1567:13;8986:55;;8807:242::o;2293:101:0:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;8951:75:25:-;1531:13:0;:11;:13::i;:::-;9017:1:25::1;9002:12;:16:::0;8951:75::o;6119:106::-;1531:13:0;:11;:13::i;:::-;6193:10:25::1;:24:::0;6119:106::o;8650:71::-;1531:13:0;:11;:13::i;:::-;8712:1:25::1;8697:12;:16:::0;8650:71::o;9509:203::-;1531:13:0;:11;:13::i;:::-;9580:21:25::1;9620:11:::0;9612:44:::1;;;::::0;-1:-1:-1;;;9612:44:25;;18664:2:26;9612:44:25::1;::::0;::::1;18646:21:26::0;18703:2;18683:18;;;18676:30;-1:-1:-1;;;18722:18:26;;;18715:50;18782:18;;9612:44:25::1;18462:344:26::0;9612:44:25::1;9667:37;::::0;9675:10:::1;::::0;9667:37;::::1;;;::::0;9696:7;;9667:37:::1;::::0;;;9696:7;9675:10;9667:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;790:27:::0;;;;;;;:::i;12057:104:13:-;12113:13;12146:7;12139:14;;;;;:::i;9112:378:12:-;9226:17;;9197:4;;-1:-1:-1;;;;;9226:17:12;9218:40;9214:244;;9282:17;;9346:60;;-1:-1:-1;;;9346:60:12;;9400:4;9346:60;;;342:51:26;-1:-1:-1;;;;;9282:17:12;;;;:45;;:17;;9346:45;;315:18:26;;9346:60:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;;9282:164;;-1:-1:-1;;;;;;9282:164:12;;;;;;;-1:-1:-1;;;;;20220:45:26;;;9282:164:12;;;20202:64:26;-1:-1:-1;;;;;20302:32:26;;20282:18;;;20275:60;20175:18;;9282:164:12;20028:313:26;19688:234:13;735:10:5;19783:39:13;;;;:18;:39;;;;;;;;-1:-1:-1;;;;;19783:49:13;;;;;;;;;;:60;;-1:-1:-1;;19783:60:13;;;;;;;:49;-1:-1:-1;;;;;19859:55:13;;19905:8;19859:55;;;;955:14:26;948:22;930:41;;918:2;903:18;;790:187;19859:55:13;;;;;;;;19688:234;;:::o;5521:818:12:-;5597:31;:29;:31::i;:::-;5641:29;-1:-1:-1;;;;;5694:30:12;;;:34;5691:304;;5749:95;;-1:-1:-1;;;5749:95:12;;5795:48;5749:95;;;22634:52:26;-1:-1:-1;;;;;5749:45:12;;;;;22607:18:26;;5749:95:12;;;;;;;;;;;;;;;;;;-1:-1:-1;5749:95:12;;;;;;;;-1:-1:-1;;5749:95:12;;;;;;;;;;;;:::i;:::-;;;5745:239;;;5942:17;-1:-1:-1;5745:239:12;-1:-1:-1;;;;;6010:32:12;;;;;;:61;;;6047:24;6046:25;6010:61;6007:152;;;6095:52;;-1:-1:-1;;;6095:52:12;;;;;;;;;;;6007:152;6209:17;;6176:72;;;-1:-1:-1;;;;;6209:17:12;;;22871:51:26;;22958:32;;;22953:2;22938:18;;22931:60;6176:72:12;;22844:18:26;6176:72:12;;;;;;;-1:-1:-1;6261:17:12;:70;;-1:-1:-1;;;;;;6261:70:12;-1:-1:-1;;;;;6261:70:12;;;;;;;;;;5521:818::o;27803:416:13:-;27978:31;27991:4;27997:2;28001:7;27978:12;:31::i;:::-;-1:-1:-1;;;;;28024:14:13;;;:19;28020:192;;28063:56;28094:4;28100:2;28104:7;28113:5;28063:30;:56::i;:::-;28058:154;;28140:56;-1:-1:-1;;;28140:7:13;:56::i;1968:1881:25:-;1284:10;1298:9;1284:23;1276:69;;;;-1:-1:-1;;;1276:69:25;;23204:2:26;1276:69:25;;;23186:21:26;23243:2;23223:18;;;23216:30;23282:34;23262:18;;;23255:62;-1:-1:-1;;;23333:18:26;;;23326:31;23374:19;;1276:69:25;23002:397:26;1276:69:25;2127:1:::1;2116:8;:12;2112:46;;;2137:21;;-1:-1:-1::0;;;2137:21:25::1;;;;;;;;;;;2112:46;2244:9;;2233:8;2217:13;5225:1:::0;7527:12:13;7144:14;7511:13;:28;-1:-1:-1;;7511:46:13;;7083:573;2217:13:25::1;:24;;;;:::i;:::-;:36;2213:70;;;2262:21;;-1:-1:-1::0;;;2262:21:25::1;;;;;;;;;;;2213:70;2373:12;;2389:1;2373:17:::0;2369:48:::1;;2399:18;;-1:-1:-1::0;;;2399:18:25::1;;;;;;;;;;;2369:48;2509:12;;2525:1;2509:17:::0;2505:1098:::1;;2593:10;2543:24;2570:34:::0;;;:22:::1;:34;::::0;;;;;;2653:39:::1;::::0;2679:12;;2653:13:::1;:39::i;:::-;2623:136;;;::::0;-1:-1:-1;;;2623:136:25;;23736:2:26;2623:136:25::1;::::0;::::1;23718:21:26::0;23775:2;23755:18;;;23748:30;23814:25;23794:18;;;23787:53;23857:18;;2623:136:25::1;23534:347:26::0;2623:136:25::1;2836:8;;2824;2808:13;5225:1:::0;7527:12:13;7144:14;7511:13;:28;-1:-1:-1;;7511:46:13;;7083:573;2808:13:25::1;:24;;;;:::i;:::-;:36;;2778:133;;;::::0;-1:-1:-1;;;2778:133:25;;24088:2:26;2778:133:25::1;::::0;::::1;24070:21:26::0;24127:2;24107:18;;;24100:30;-1:-1:-1;;;24146:18:26;;;24139:52;24208:18;;2778:133:25::1;23886:346:26::0;2778:133:25::1;2991:14;::::0;2960:27:::1;2979:8:::0;2960:16;:27:::1;:::i;:::-;:45;;2930:147;;;::::0;-1:-1:-1;;;2930:147:25;;24439:2:26;2930:147:25::1;::::0;::::1;24421:21:26::0;24478:2;24458:18;;;24451:30;24517;24497:18;;;24490:58;24565:18;;2930:147:25::1;24237:352:26::0;2930:147:25::1;3155:8;3139:13;;:24;;;;:::i;:::-;3126:9;:37;;3096:129;;;::::0;-1:-1:-1;;;3096:129:25;;24796:2:26;3096:129:25::1;::::0;::::1;24778:21:26::0;24835:2;24815:18;;;24808:30;-1:-1:-1;;;24854:18:26;;;24847:48;24912:18;;3096:129:25::1;24594:342:26::0;3096:129:25::1;2528:713;2505:1098;;;3251:12;;3267:1;3251:17:::0;3247:356:::1;;3330:10;3289:24;3316:25:::0;;;:13:::1;:25;::::0;;;;;3421:12:::1;::::0;3390:27:::1;3409:8:::0;3316:25;3390:27:::1;:::i;:::-;:43;;3360:145;;;::::0;-1:-1:-1;;;3360:145:25;;24439:2:26;3360:145:25::1;::::0;::::1;24421:21:26::0;24478:2;24458:18;;;24451:30;24517;24497:18;;;24490:58;24565:18;;3360:145:25::1;24237:352:26::0;3360:145:25::1;3556:8;3545;;:19;;;;:::i;:::-;3532:9;:32;;3524:63;;;::::0;-1:-1:-1;;;3524:63:25;;24796:2:26;3524:63:25::1;::::0;::::1;24778:21:26::0;24835:2;24815:18;;;24808:30;-1:-1:-1;;;24854:18:26;;;24847:48;24912:18;;3524:63:25::1;24594:342:26::0;3524:63:25::1;3270:333;3247:356;3615:27;3621:10;3633:8;3615:5;:27::i;:::-;3657:12;;3673:1;3657:17:::0;3653:189:::1;;3714:10;3691:34;::::0;;;:22:::1;:34;::::0;;;;:46;;3729:8;;3691:34;:46:::1;::::0;3729:8;;3691:46:::1;:::i;:::-;::::0;;;-1:-1:-1;3653:189:25::1;::::0;-1:-1:-1;3653:189:25::1;;3759:12;;3775:1;3759:17:::0;3755:87:::1;;3807:10;3793:25;::::0;;;:13:::1;:25;::::0;;;;:37;;3822:8;;3793:25;:37:::1;::::0;3822:8;;3793:37:::1;:::i;:::-;::::0;;;-1:-1:-1;;1968:1881:25;;;:::o;4847:231::-;1531:13:0;:11;:13::i;:::-;4964:9:25::1;;4953:8;4937:13;5225:1:::0;7527:12:13;7144:14;7511:13;:28;-1:-1:-1;;7511:46:13;;7083:573;4937:13:25::1;:24;;;;:::i;:::-;:36;4933:97;;;4997:21;;-1:-1:-1::0;;;4997:21:25::1;;;;;;;;;;;4933:97;5042:28;5048:11;5061:8;5042:5;:28::i;6808:455:12:-:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;6923:17:12;;-1:-1:-1;;;;;6923:17:12;6915:40;6911:140;;6979:17;;:60;;-1:-1:-1;;;6979:60:12;;7033:4;6979:60;;;342:51:26;-1:-1:-1;;;;;6979:17:12;;;;:45;;315:18:26;;6979:60:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;6911:140::-;-1:-1:-1;7070:185:12;;;;;;;;-1:-1:-1;7070:185:12;;;;;;;;;;;;;;;;;6808:455::o;5538:422:25:-;5603:13;5638:16;5646:7;5638;:16::i;:::-;5629:61;;;;-1:-1:-1;;;5629:61:25;;25143:2:26;5629:61:25;;;25125:21:26;25182:2;25162:18;;;25155:30;25221:33;25201:18;;;25194:61;25272:18;;5629:61:25;24941:355:26;5629:61:25;5710:8;;;;:17;;:8;:17;5707:47;;5738:13;5731:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5538:422;;;:::o;5707:47::-;5766:28;5797:10;:8;:10::i;:::-;5766:41;;5856:1;5831:14;5825:28;:32;:127;;;;;;;;;;;;;;;;;5893:14;5909:18;5919:7;5909:9;:18::i;:::-;5876:61;;;;;;;;;:::i;:::-;;;;;;;;;;;;;5818:134;5538:422;-1:-1:-1;;;5538:422:25:o;8038:379:12:-;8150:17;;8109:16;;-1:-1:-1;;;;;8150:17:12;8142:40;8138:236;;8206:17;;8272:60;;-1:-1:-1;;;8272:60:12;;8326:4;8272:60;;;342:51:26;-1:-1:-1;;;;;8206:17:12;;;;:47;;:17;;8272:45;;315:18:26;;8272:60:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:89;;;;;8206:156;;-1:-1:-1;;;;;;8206:156:12;;;;;;;-1:-1:-1;;;;;9276:45:26;;;8206:156:12;;;9258:64:26;9231:18;;8206:156:12;9112:216:26;7935:77:25;1531:13:0;:11;:13::i;:::-;7991:6:25::1;:13:::0;;-1:-1:-1;;7991:13:25::1;;;::::0;;7935:77::o;7288:96::-;1531:13:0;:11;:13::i;:::-;7357:8:25::1;:19:::0;7288:96::o;7744:102::-;1531:13:0;:11;:13::i;:::-;1184:6:25::1;::::0;::::1;::::0;::::1;;;1183:7;1175:47;;;;-1:-1:-1::0;;;1175:47:25::1;;;;;;;:::i;:::-;7821:8:::2;:17:::0;;-1:-1:-1;;7821:17:25::2;::::0;::::2;;::::0;;;::::2;::::0;;7744:102::o;6358:100::-;1531:13:0;:11;:13::i;:::-;6429:12:25::1;:21:::0;6358:100::o;2543:215:0:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:0;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:0;;2700:1:::1;2672:31;::::0;::::1;342:51:26::0;315:18;;2672:31:0::1;196:203:26::0;2623:91:0::1;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;7072:100:25:-;1531:13:0;:11;:13::i;:::-;7143:8:25::1;:21:::0;7072:100::o;3252:749:12:-;3482:31;:29;:31::i;:::-;3526;3547:9;3526:20;:31::i;:::-;3570:114;;-1:-1:-1;;;3570:114:12;;-1:-1:-1;;;;;3570:92:12;;;;;:114;;3671:4;;3678:5;;3570:114;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3697:124:12;;-1:-1:-1;;;3697:124:12;;-1:-1:-1;;;;;3697:88:12;;;-1:-1:-1;3697:88:12;;-1:-1:-1;3697:124:12;;3794:4;;3801:19;;3697:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3834:159:12;;-1:-1:-1;;;3834:159:12;;-1:-1:-1;;;;;3834:105:12;;;-1:-1:-1;3834:105:12;;-1:-1:-1;3834:159:12;;3948:4;;3955:37;;3834:159;;;:::i;2116:213:3:-;2218:4;-1:-1:-1;;;;;;2241:41:3;;-1:-1:-1;;;2241:41:3;;:81;;-1:-1:-1;;;;;;;;;;862:40:9;;;2286:36:3;763:146:9;223:104:21;306:13;:11;:13::i;542:217:11:-;646:48;671:8;681:12;646:24;:48::i;:::-;710:41;;-1:-1:-1;;;;;26110:39:26;;26092:58;;-1:-1:-1;;;;;710:41:11;;;;;26080:2:26;26065:18;710:41:11;;;;;;;542:217;;:::o;20501:475:13:-;20566:11;20613:7;5225:1:25;20594:26:13;20590:379;;20758:13;;20748:7;:23;20744:214;;;20792:14;20825:60;-1:-1:-1;20842:26:13;;;;:17;:26;;;;;;;20832:42;;;20825:60;;20876:9;;;:::i;:::-;;;20825:60;;;-1:-1:-1;;;20913:24:13;:29;;-1:-1:-1;20744:214:13;20501:475;;;:::o;51010:165::-;51111:13;51105:4;51098:27;51152:4;51146;51139:18;42425:474;42554:13;42570:16;42578:7;42570;:16::i;:::-;42554:32;;42603:13;:45;;;;-1:-1:-1;735:10:5;-1:-1:-1;;;;;42620:28:13;;;;42603:45;42599:201;;;42668:44;42685:5;735:10:5;42692:19:13;7470:358:12;42668:44:13;42663:137;;42733:51;-1:-1:-1;;;42733:7:13;:51::i;:::-;42812:24;;;;:15;:24;;;;;;:35;;-1:-1:-1;;;;;;42812:35:13;-1:-1:-1;;;;;42812:35:13;;;;;;;;;42863:28;;42812:24;;42863:28;;;;;;;42543:356;42425:474;;;:::o;1796:162:0:-;1710:6;;-1:-1:-1;;;;;1710:6:0;735:10:5;1855:23:0;1851:101;;1901:40;;-1:-1:-1;;;1901:40:0;;735:10:5;1901:40:0;;;342:51:26;315:18;;1901:40:0;196:203:26;14768:2213:13;14835:14;14885:7;5225:1:25;14866:26:13;14862:2054;;-1:-1:-1;14918:26:13;;;;:17;:26;;;;;;15245:6;15255:1;15245:11;15241:1292;;15292:13;;15281:7;:24;15277:77;;15307:47;-1:-1:-1;;;15307:7:13;:47::i;:::-;15911:607;-1:-1:-1;;;16007:9:13;15989:28;;;;:17;:28;;;;;;16063:25;;15911:607;16063:25;-1:-1:-1;;;16115:6:13;:24;16143:1;16115:29;16111:48;;14768:2213;;;:::o;16111:48::-;16451:47;-1:-1:-1;;;16451:7:13;:47::i;:::-;15911:607;;15241:1292;-1:-1:-1;;;16860:6:13;:24;16888:1;16860:29;16856:48;;14768:2213;;;:::o;16856:48::-;16926:47;-1:-1:-1;;;16926:7:13;:47::i;978:359:14:-;1160:9;1155:175;1179:8;1175:1;:12;1155:175;;;1205:51;1229:4;1235:2;1239:16;1254:1;1239:12;:16;:::i;:::-;1205:23;:51::i;:::-;1300:3;;1155:175;;;;978:359;;;;:::o;1444:357::-;1625:9;1620:174;1644:8;1640:1;:12;1620:174;;;1670:50;1693:4;1699:2;1703:16;1718:1;1703:12;:16;:::i;:::-;1670:22;:50::i;:::-;1764:3;;1620:174;;767:246:11;886:55;909:7;918:8;928:12;886:22;:55::i;:::-;957:48;;-1:-1:-1;;;;;26110:39:26;;26092:58;;-1:-1:-1;;;;;957:48:11;;;973:7;;957:48;;26080:2:26;26065:18;957:48:11;;;;;;;767:246;;;:::o;1902:154:8:-;1993:4;2045;2016:25;2029:5;2036:4;2016:12;:25::i;:::-;:33;;1902:154;-1:-1:-1;;;;1902:154:8:o;2912:187:0:-;3004:6;;;-1:-1:-1;;;;;3020:17:0;;;-1:-1:-1;;;;;;3020:17:0;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;30303:691:13:-;30487:88;;-1:-1:-1;;;30487:88:13;;30466:4;;-1:-1:-1;;;;;30487:45:13;;;;;:88;;735:10:5;;30554:4:13;;30560:7;;30569:5;;30487:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;30487:88:13;;;;;;;;-1:-1:-1;;30487:88:13;;;;;;;;;;;;:::i;:::-;;;30483:504;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30770:6;:13;30787:1;30770:18;30766:115;;30809:56;-1:-1:-1;;;30809:7:13;:56::i;:::-;30953:6;30947:13;30938:6;30934:2;30930:15;30923:38;30483:504;-1:-1:-1;;;;;;30646:64:13;-1:-1:-1;;;30646:64:13;;-1:-1:-1;30483:504:13;30303:691;;;;;;:::o;31456:2399::-;31529:20;31552:13;;;31580;;;31576:53;;31595:34;-1:-1:-1;;;31595:7:13;:34::i;:::-;31642:61;31672:1;31676:2;31680:12;31694:8;31642:21;:61::i;:::-;32142:31;;;;:17;:31;;;;;;;;-1:-1:-1;;;;;17766:28:13;;17940:11;17915:23;17911:41;18384:1;18371:15;;18345:24;18341:46;17908:52;17898:63;;32142:173;;;32533:22;;;:18;:22;;;;;:71;;32571:32;32559:45;;32533:71;;;17766:28;32794:13;;;32790:54;;32809:35;-1:-1:-1;;;32809:7:13;:35::i;:::-;32875:23;;;;33054:676;33473:7;33429:8;33384:1;33318:25;33255:1;33190;33159:358;33725:3;33712:9;;;;;;:16;33054:676;;-1:-1:-1;33746:13:13;:19;;;33787:60;;-1:-1:-1;33820:2:13;33824:12;33838:8;33787:20;:60::i;5310:100:25:-;5362:13;5395:7;5388:14;;;;;:::i;49198:1745:13:-;49263:17;49697:4;49690;49684:11;49680:22;49789:1;49783:4;49776:15;49864:4;49861:1;49857:12;49850:19;;;49946:1;49941:3;49934:14;50050:3;50289:5;50271:428;50337:1;50332:3;50328:11;50321:18;;50508:2;50502:4;50498:13;50494:2;50490:22;50485:3;50477:36;50602:2;50592:13;;50659:25;50271:428;50659:25;-1:-1:-1;50729:13:13;;;-1:-1:-1;;50844:14:13;;;50906:19;;;50844:14;49198:1745;-1:-1:-1;49198:1745:13:o;3667:507:3:-;3394:5;-1:-1:-1;;;;;3814:26:3;;;-1:-1:-1;3810:173:3;;;3917:55;;-1:-1:-1;;;3917:55:3;;-1:-1:-1;;;;;27248:39:26;;3917:55:3;;;27230:58:26;27304:18;;;27297:34;;;27203:18;;3917:55:3;27057:280:26;3810:173:3;-1:-1:-1;;;;;3996:22:3;;3992:108;;4041:48;;-1:-1:-1;;;4041:48:3;;4086:1;4041:48;;;342:51:26;315:18;;4041:48:3;196:203:26;3992:108:3;-1:-1:-1;4132:35:3;;;;;;;;;-1:-1:-1;;;;;4132:35:3;;;;;;-1:-1:-1;;;;;4132:35:3;;;;;;;;;;-1:-1:-1;;;4110:57:3;;;;:19;:57;3667:507::o;714:623:24:-;-1:-1:-1;;;;;841:18:24;;;;;891:16;;;841:18;923:32;;;;;942:13;923:32;920:410;;;979:28;;-1:-1:-1;;;979:28:24;;;;;;;;;;;920:410;1028:15;1025:305;;;1060:54;1025:305;;;1135:13;1165:56;1132:198;1254:64;735:10:5;1289:4:24;1295:2;1299:7;1308:9;1254:20;:64::i;1470:625::-;-1:-1:-1;;;;;1596:18:24;;;;;1646:16;;;1596:18;1678:32;;;;;1697:13;1678:32;1675:413;;;1734:28;;-1:-1:-1;;;1734:28:24;;;;;;;;;;;1675:413;1783:15;1815:55;1780:308;1891:13;1921:57;1888:200;2011:65;2543:215:0:o;4608:543:3:-;3394:5;-1:-1:-1;;;;;4770:26:3;;;-1:-1:-1;4766:180:3;;;4873:62;;-1:-1:-1;;;4873:62:3;;;;;27543:25:26;;;-1:-1:-1;;;;;27604:39:26;;27584:18;;;27577:67;27660:18;;;27653:34;;;27516:18;;4873:62:3;27342:351:26;4766:180:3;-1:-1:-1;;;;;4959:22:3;;4955:115;;5004:55;;-1:-1:-1;;;5004:55:3;;;;;27872:25:26;;;5056:1:3;27913:18:26;;;27906:60;27845:18;;5004:55:3;27698:274:26;4955:115:3;-1:-1:-1;5109:35:3;;;;;;;;-1:-1:-1;;;;;5109:35:3;;;;;-1:-1:-1;;;;;5109:35:3;;;;;;;;;;-1:-1:-1;5080:26:3;;;:17;:26;;;;;;:64;;;;;;;-1:-1:-1;;;5080:64:3;;;;;;4608:543::o;2457:308:8:-;2540:7;2582:4;2540:7;2596:134;2620:5;:12;2616:1;:16;2596:134;;;2668:51;2696:12;2710:5;2716:1;2710:8;;;;;;;;:::i;:::-;;;;;;;2668:27;:51::i;:::-;2653:66;-1:-1:-1;2634:3:8;;2596:134;;;-1:-1:-1;2746:12:8;2457:308;-1:-1:-1;;;2457:308:8:o;11328:344:12:-;11539:17;;-1:-1:-1;;;;;11539:17:12;11531:40;11527:138;;11588:17;;:65;;-1:-1:-1;;;11588:65:12;;-1:-1:-1;;;;;17885:32:26;;;11588:65:12;;;17867:51:26;17954:32;;;17934:18;;;17927:60;18023:32;;;18003:18;;;17996:60;11588:17:12;;;;:47;;17840:18:26;;11588:65:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11328:344;;;;;:::o;504:169:7:-;579:7;609:1;605;:5;:61;;866:13;930:15;;;965:4;958:15;;;1011:4;995:21;;605:61;;;-1:-1:-1;866:13:7;930:15;;;965:4;958:15;1011:4;995:21;;;504:169::o;404:131:26:-;-1:-1:-1;;;;;;478:32:26;;468:43;;458:71;;525:1;522;515:12;540:245;598:6;651:2;639:9;630:7;626:23;622:32;619:52;;;667:1;664;657:12;619:52;706:9;693:23;725:30;749:5;725:30;:::i;982:131::-;-1:-1:-1;;;;;1057:31:26;;1047:42;;1037:70;;1103:1;1100;1093:12;1118:179;1185:20;;-1:-1:-1;;;;;1234:38:26;;1224:49;;1214:77;;1287:1;1284;1277:12;1302:319;1369:6;1377;1430:2;1418:9;1409:7;1405:23;1401:32;1398:52;;;1446:1;1443;1436:12;1398:52;1485:9;1472:23;1504:31;1529:5;1504:31;:::i;:::-;1554:5;-1:-1:-1;1578:37:26;1611:2;1596:18;;1578:37;:::i;:::-;1568:47;;1302:319;;;;;:::o;1626:300::-;1679:3;1717:5;1711:12;1744:6;1739:3;1732:19;1800:6;1793:4;1786:5;1782:16;1775:4;1770:3;1766:14;1760:47;1852:1;1845:4;1836:6;1831:3;1827:16;1823:27;1816:38;1915:4;1908:2;1904:7;1899:2;1891:6;1887:15;1883:29;1878:3;1874:39;1870:50;1863:57;;;1626:300;;;;:::o;1931:231::-;2080:2;2069:9;2062:21;2043:4;2100:56;2152:2;2141:9;2137:18;2129:6;2100:56;:::i;2167:247::-;2226:6;2279:2;2267:9;2258:7;2254:23;2250:32;2247:52;;;2295:1;2292;2285:12;2247:52;2334:9;2321:23;2353:31;2378:5;2353:31;:::i;2419:226::-;2478:6;2531:2;2519:9;2510:7;2506:23;2502:32;2499:52;;;2547:1;2544;2537:12;2499:52;-1:-1:-1;2592:23:26;;2419:226;-1:-1:-1;2419:226:26:o;2650:367::-;2718:6;2726;2779:2;2767:9;2758:7;2754:23;2750:32;2747:52;;;2795:1;2792;2785:12;2747:52;2834:9;2821:23;2853:31;2878:5;2853:31;:::i;:::-;2903:5;2981:2;2966:18;;;;2953:32;;-1:-1:-1;;;2650:367:26:o;3269:127::-;3330:10;3325:3;3321:20;3318:1;3311:31;3361:4;3358:1;3351:15;3385:4;3382:1;3375:15;3401:275;3472:2;3466:9;3537:2;3518:13;;-1:-1:-1;;3514:27:26;3502:40;;3572:18;3557:34;;3593:22;;;3554:62;3551:88;;;3619:18;;:::i;:::-;3655:2;3648:22;3401:275;;-1:-1:-1;3401:275:26:o;3681:450::-;3746:5;3778:1;3802:18;3794:6;3791:30;3788:56;;;3824:18;;:::i;:::-;-1:-1:-1;3890:2:26;3869:15;;-1:-1:-1;;3865:29:26;3896:4;3861:40;3919:21;3861:40;3919:21;:::i;:::-;3910:30;;;3963:6;3956:5;3949:21;4003:3;3994:6;3989:3;3985:16;3982:25;3979:45;;;4020:1;4017;4010:12;3979:45;4069:6;4064:3;4057:4;4050:5;4046:16;4033:43;4123:1;4116:4;4107:6;4100:5;4096:18;4092:29;4085:40;3681:450;;;;;:::o;4136:451::-;4205:6;4258:2;4246:9;4237:7;4233:23;4229:32;4226:52;;;4274:1;4271;4264:12;4226:52;4314:9;4301:23;4347:18;4339:6;4336:30;4333:50;;;4379:1;4376;4369:12;4333:50;4402:22;;4455:4;4447:13;;4443:27;-1:-1:-1;4433:55:26;;4484:1;4481;4474:12;4433:55;4507:74;4573:7;4568:2;4555:16;4550:2;4546;4542:11;4507:74;:::i;4592:529::-;4669:6;4677;4685;4738:2;4726:9;4717:7;4713:23;4709:32;4706:52;;;4754:1;4751;4744:12;4706:52;4793:9;4780:23;4812:31;4837:5;4812:31;:::i;:::-;4862:5;-1:-1:-1;4919:2:26;4904:18;;4891:32;4932:33;4891:32;4932:33;:::i;:::-;4984:7;-1:-1:-1;5043:2:26;5028:18;;5015:32;5056:33;5015:32;5056:33;:::i;:::-;5108:7;5098:17;;;4592:529;;;;;:::o;5258:250::-;5352:1;5345:5;5342:12;5332:143;;5397:10;5392:3;5388:20;5385:1;5378:31;5432:4;5429:1;5422:15;5460:4;5457:1;5450:15;5332:143;5484:18;;5258:250::o;5513:234::-;5672:2;5657:18;;5684:57;5661:9;5723:6;5684:57;:::i;5752:508::-;5829:6;5837;5845;5898:2;5886:9;5877:7;5873:23;5869:32;5866:52;;;5914:1;5911;5904:12;5866:52;5953:9;5940:23;5972:31;5997:5;5972:31;:::i;:::-;6022:5;-1:-1:-1;6079:2:26;6064:18;;6051:32;6092:33;6051:32;6092:33;:::i;:::-;5752:508;;6144:7;;-1:-1:-1;;;6224:2:26;6209:18;;;;6196:32;;5752:508::o;6265:346::-;6333:6;6341;6394:2;6382:9;6373:7;6369:23;6365:32;6362:52;;;6410:1;6407;6400:12;6362:52;-1:-1:-1;;6455:23:26;;;6575:2;6560:18;;;6547:32;;-1:-1:-1;6265:346:26:o;7077:637::-;7267:2;7279:21;;;7349:13;;7252:18;;;7371:22;;;7219:4;;7450:15;;;7424:2;7409:18;;;7219:4;7493:195;7507:6;7504:1;7501:13;7493:195;;;7572:13;;-1:-1:-1;;;;;7568:39:26;7556:52;;7637:2;7663:15;;;;7628:12;;;;7604:1;7522:9;7493:195;;;-1:-1:-1;7705:3:26;;7077:637;-1:-1:-1;;;;;7077:637:26:o;7719:439::-;7795:6;7803;7811;7864:2;7852:9;7843:7;7839:23;7835:32;7832:52;;;7880:1;7877;7870:12;7832:52;7925:23;;;-1:-1:-1;8024:2:26;8009:18;;7996:32;8037:33;7996:32;8037:33;:::i;:::-;8089:7;-1:-1:-1;8115:37:26;8148:2;8133:18;;8115:37;:::i;:::-;8105:47;;7719:439;;;;;:::o;8163:367::-;8226:8;8236:6;8290:3;8283:4;8275:6;8271:17;8267:27;8257:55;;8308:1;8305;8298:12;8257:55;-1:-1:-1;8331:20:26;;8374:18;8363:30;;8360:50;;;8406:1;8403;8396:12;8360:50;8443:4;8435:6;8431:17;8419:29;;8503:3;8496:4;8486:6;8483:1;8479:14;8471:6;8467:27;8463:38;8460:47;8457:67;;;8520:1;8517;8510:12;8535:572;8630:6;8638;8646;8699:2;8687:9;8678:7;8674:23;8670:32;8667:52;;;8715:1;8712;8705:12;8667:52;8754:9;8741:23;8773:31;8798:5;8773:31;:::i;:::-;8823:5;-1:-1:-1;8879:2:26;8864:18;;8851:32;8906:18;8895:30;;8892:50;;;8938:1;8935;8928:12;8892:50;8977:70;9039:7;9030:6;9019:9;9015:22;8977:70;:::i;:::-;8535:572;;9066:8;;-1:-1:-1;8951:96:26;;-1:-1:-1;;;;8535:572:26:o;9333:121::-;9428:1;9421:5;9418:12;9408:40;;9444:1;9441;9434:12;9459:144;-1:-1:-1;;;;;9538:5:26;9534:44;9527:5;9524:55;9514:83;;9593:1;9590;9583:12;9608:576;9712:6;9720;9728;9781:2;9769:9;9760:7;9756:23;9752:32;9749:52;;;9797:1;9794;9787:12;9749:52;9836:9;9823:23;9855:51;9900:5;9855:51;:::i;:::-;9925:5;-1:-1:-1;9982:2:26;9967:18;;9954:32;9995:33;9954:32;9995:33;:::i;:::-;10047:7;-1:-1:-1;10106:2:26;10091:18;;10078:32;10119:33;10078:32;10119:33;:::i;10374:118::-;10460:5;10453:13;10446:21;10439:5;10436:32;10426:60;;10482:1;10479;10472:12;10497:382;10562:6;10570;10623:2;10611:9;10602:7;10598:23;10594:32;10591:52;;;10639:1;10636;10629:12;10591:52;10678:9;10665:23;10697:31;10722:5;10697:31;:::i;:::-;10747:5;-1:-1:-1;10804:2:26;10789:18;;10776:32;10817:30;10776:32;10817:30;:::i;:::-;10866:7;10856:17;;;10497:382;;;;;:::o;10884:847::-;10979:6;10987;10995;11003;11056:3;11044:9;11035:7;11031:23;11027:33;11024:53;;;11073:1;11070;11063:12;11024:53;11112:9;11099:23;11131:31;11156:5;11131:31;:::i;:::-;11181:5;-1:-1:-1;11238:2:26;11223:18;;11210:32;11251:33;11210:32;11251:33;:::i;:::-;11303:7;-1:-1:-1;11383:2:26;11368:18;;11355:32;;-1:-1:-1;11464:2:26;11449:18;;11436:32;11491:18;11480:30;;11477:50;;;11523:1;11520;11513:12;11477:50;11546:22;;11599:4;11591:13;;11587:27;-1:-1:-1;11577:55:26;;11628:1;11625;11618:12;11577:55;11651:74;11717:7;11712:2;11699:16;11694:2;11690;11686:11;11651:74;:::i;:::-;11641:84;;;10884:847;;;;;;;:::o;11736:551::-;11831:6;11839;11847;11900:2;11888:9;11879:7;11875:23;11871:32;11868:52;;;11916:1;11913;11906:12;11868:52;11961:23;;;-1:-1:-1;12059:2:26;12044:18;;12031:32;12086:18;12075:30;;12072:50;;;12118:1;12115;12108:12;12292:367;12360:6;12368;12421:2;12409:9;12400:7;12396:23;12392:32;12389:52;;;12437:1;12434;12427:12;12389:52;12482:23;;;-1:-1:-1;12581:2:26;12566:18;;12553:32;12594:33;12553:32;12594:33;:::i;12664:504::-;12840:4;12882:2;12871:9;12867:18;12859:26;;12894:64;12948:9;12939:6;12933:13;12894:64;:::i;:::-;-1:-1:-1;;;;;13018:4:26;13010:6;13006:17;13000:24;12996:63;12989:4;12978:9;12974:20;12967:93;-1:-1:-1;;;;;13120:4:26;13112:6;13108:17;13102:24;13098:63;13091:4;13080:9;13076:20;13069:93;12664:504;;;;:::o;13173:241::-;13229:6;13282:2;13270:9;13261:7;13257:23;13253:32;13250:52;;;13298:1;13295;13288:12;13250:52;13337:9;13324:23;13356:28;13378:5;13356:28;:::i;13419:388::-;13487:6;13495;13548:2;13536:9;13527:7;13523:23;13519:32;13516:52;;;13564:1;13561;13554:12;13516:52;13603:9;13590:23;13622:31;13647:5;13622:31;:::i;:::-;13672:5;-1:-1:-1;13729:2:26;13714:18;;13701:32;13742:33;13701:32;13742:33;:::i;13812:718::-;13925:6;13933;13941;13949;14002:3;13990:9;13981:7;13977:23;13973:33;13970:53;;;14019:1;14016;14009:12;13970:53;14058:9;14045:23;14077:31;14102:5;14077:31;:::i;:::-;14127:5;-1:-1:-1;14184:2:26;14169:18;;14156:32;14197:53;14156:32;14197:53;:::i;:::-;14269:7;-1:-1:-1;14328:2:26;14313:18;;14300:32;14341:33;14300:32;14341:33;:::i;:::-;14393:7;-1:-1:-1;14452:2:26;14437:18;;14424:32;14465:33;14424:32;14465:33;:::i;:::-;13812:718;;;;-1:-1:-1;13812:718:26;;-1:-1:-1;;13812:718:26:o;14535:380::-;14614:1;14610:12;;;;14657;;;14678:61;;14732:4;14724:6;14720:17;14710:27;;14678:61;14785:2;14777:6;14774:14;14754:18;14751:38;14748:161;;14831:10;14826:3;14822:20;14819:1;14812:31;14866:4;14863:1;14856:15;14894:4;14891:1;14884:15;14748:161;;14535:380;;;:::o;14920:127::-;14981:10;14976:3;14972:20;14969:1;14962:31;15012:4;15009:1;15002:15;15036:4;15033:1;15026:15;15052:128;15119:9;;;15140:11;;;15137:37;;;15154:18;;:::i;15185:351::-;15387:2;15369:21;;;15426:2;15406:18;;;15399:30;15465:29;15460:2;15445:18;;15438:57;15527:2;15512:18;;15185:351::o;15667:518::-;15769:2;15764:3;15761:11;15758:421;;;15805:5;15802:1;15795:16;15849:4;15846:1;15836:18;15919:2;15907:10;15903:19;15900:1;15896:27;15890:4;15886:38;15955:4;15943:10;15940:20;15937:47;;;-1:-1:-1;15978:4:26;15937:47;16033:2;16028:3;16024:12;16021:1;16017:20;16011:4;16007:31;15997:41;;16088:81;16106:2;16099:5;16096:13;16088:81;;;16165:1;16151:16;;16132:1;16121:13;16088:81;;16361:1299;16487:3;16481:10;16514:18;16506:6;16503:30;16500:56;;;16536:18;;:::i;:::-;16565:97;16655:6;16615:38;16647:4;16641:11;16615:38;:::i;:::-;16609:4;16565:97;:::i;:::-;16711:4;16742:2;16731:14;;16759:1;16754:649;;;;17447:1;17464:6;17461:89;;;-1:-1:-1;17516:19:26;;;17510:26;17461:89;-1:-1:-1;;16318:1:26;16314:11;;;16310:24;16306:29;16296:40;16342:1;16338:11;;;16293:57;17563:81;;16724:930;;16754:649;15614:1;15607:14;;;15651:4;15638:18;;-1:-1:-1;;16790:20:26;;;16908:222;16922:7;16919:1;16916:14;16908:222;;;17004:19;;;16998:26;16983:42;;17111:4;17096:20;;;;17064:1;17052:14;;;;16938:12;16908:222;;;16912:3;17158:6;17149:7;17146:19;17143:201;;;17219:19;;;17213:26;-1:-1:-1;;17302:1:26;17298:14;;;17314:3;17294:24;17290:37;17286:42;17271:58;17256:74;;17143:201;-1:-1:-1;;;;17390:1:26;17374:14;;;17370:22;17357:36;;-1:-1:-1;16361:1299:26:o;18067:168::-;18140:9;;;18171;;18188:15;;;18182:22;;18168:37;18158:71;;18209:18;;:::i;18240:217::-;18280:1;18306;18296:132;;18350:10;18345:3;18341:20;18338:1;18331:31;18385:4;18382:1;18375:15;18413:4;18410:1;18403:15;18296:132;-1:-1:-1;18442:9:26;;18240:217::o;19156:867::-;19268:6;19328:2;19316:9;19307:7;19303:23;19299:32;19343:2;19340:22;;;19358:1;19355;19348:12;19340:22;-1:-1:-1;19427:2:26;19421:9;19469:2;19457:15;;19502:18;19487:34;;19523:22;;;19484:62;19481:88;;;19549:18;;:::i;:::-;19585:2;19578:22;19622:16;;19647:51;19622:16;19647:51;:::i;:::-;19707:21;;19773:2;19758:18;;19752:25;19786:33;19752:25;19786:33;:::i;:::-;19847:2;19835:15;;19828:32;19905:2;19890:18;;19884:25;19918:33;19884:25;19918:33;:::i;:::-;19979:2;19967:15;;19960:32;19971:6;19156:867;-1:-1:-1;;;19156:867:26:o;20346:245::-;20413:6;20466:2;20454:9;20445:7;20441:23;20437:32;20434:52;;;20482:1;20479;20472:12;20434:52;20514:9;20508:16;20533:28;20555:5;20533:28;:::i;20596:1001::-;20691:6;20744:2;20732:9;20723:7;20719:23;20715:32;20712:52;;;20760:1;20757;20750:12;20712:52;20793:9;20787:16;20826:18;20818:6;20815:30;20812:50;;;20858:1;20855;20848:12;20812:50;20881:22;;20934:4;20926:13;;20922:27;-1:-1:-1;20912:55:26;;20963:1;20960;20953:12;20912:55;20996:2;20990:9;21022:18;21014:6;21011:30;21008:56;;;21044:18;;:::i;:::-;21090:6;21087:1;21083:14;21117:28;21141:2;21137;21133:11;21117:28;:::i;:::-;21179:19;;;21223:2;21253:11;;;21249:20;;;21214:12;;;;21281:19;;;21278:39;;;21313:1;21310;21303:12;21278:39;21345:2;21341;21337:11;21326:22;;21357:210;21373:6;21368:3;21365:15;21357:210;;;21446:3;21440:10;21427:23;;21463:31;21488:5;21463:31;:::i;:::-;21507:18;;;21554:2;21390:12;;;;21545;;;;21357:210;;;21586:5;20596:1001;-1:-1:-1;;;;;;;20596:1001:26:o;21836:331::-;-1:-1:-1;;;;;22053:32:26;;22035:51;;22023:2;22008:18;;22095:66;22157:2;22142:18;;22134:6;22095:66;:::i;22172:313::-;-1:-1:-1;;;;;22364:32:26;;;;22346:51;;-1:-1:-1;;;;;22433:45:26;22428:2;22413:18;;22406:73;22334:2;22319:18;;22172:313::o;23404:125::-;23469:9;;;23490:10;;;23487:36;;;23503:18;;:::i;25301:212::-;25343:3;25381:5;25375:12;25425:6;25418:4;25411:5;25407:16;25402:3;25396:36;25487:1;25451:16;;25476:13;;;-1:-1:-1;25451:16:26;;25301:212;-1:-1:-1;25301:212:26:o;25518:425::-;25798:3;25826:57;25852:30;25878:3;25870:6;25852:30;:::i;:::-;25844:6;25826:57;:::i;:::-;-1:-1:-1;;;25892:19:26;;25935:1;25927:10;;25518:425;-1:-1:-1;;;;25518:425:26:o;26161:136::-;26200:3;26228:5;26218:39;;26237:18;;:::i;:::-;-1:-1:-1;;;26273:18:26;;26161:136::o;26302:496::-;-1:-1:-1;;;;;26533:32:26;;;26515:51;;26602:32;;26597:2;26582:18;;26575:60;26666:2;26651:18;;26644:34;;;26714:3;26709:2;26694:18;;26687:31;;;-1:-1:-1;;26735:57:26;;26772:19;;26764:6;26735:57;:::i;:::-;26727:65;26302:496;-1:-1:-1;;;;;;26302:496:26:o;26803:249::-;26872:6;26925:2;26913:9;26904:7;26900:23;26896:32;26893:52;;;26941:1;26938;26931:12;26893:52;26973:9;26967:16;26992:30;27016:5;26992:30;:::i;27977:127::-;28038:10;28033:3;28029:20;28026:1;28019:31;28069:4;28066:1;28059:15;28093:4;28090:1;28083:15
Swarm Source
ipfs://dd0738d8066e9ad5f833c3ac142499d0d134076f3a694674f62b4bbf7b3ff43e
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.