ETH Price: $3,139.66 (-5.29%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Approval For...216927862025-01-24 7:12:113 days ago1737702731IN
0x864D6DC0...E1178DAB7
0 ETH0.000194194.17397616
Set Approval For...216312442025-01-15 17:01:5911 days ago1736960519IN
0x864D6DC0...E1178DAB7
0 ETH0.0008563218.40523077
Set Approval For...216272092025-01-15 3:29:5912 days ago1736911799IN
0x864D6DC0...E1178DAB7
0 ETH0.000148573.19329761
Set Approval For...216113112025-01-12 22:11:2314 days ago1736719883IN
0x864D6DC0...E1178DAB7
0 ETH0.000186644.01152946
Set Approval For...215668762025-01-06 17:20:4720 days ago1736184047IN
0x864D6DC0...E1178DAB7
0 ETH0.0011457924.58256839
Set Approval For...215599972025-01-05 18:13:5921 days ago1736100839IN
0x864D6DC0...E1178DAB7
0 ETH0.000388768.35589997
Set Approval For...215551162025-01-05 1:52:1122 days ago1736041931IN
0x864D6DC0...E1178DAB7
0 ETH0.000319146.84720424
Set Approval For...215375822025-01-02 15:08:1125 days ago1735830491IN
0x864D6DC0...E1178DAB7
0 ETH0.0003774415.28227222
Set Approval For...215374862025-01-02 14:48:5925 days ago1735829339IN
0x864D6DC0...E1178DAB7
0 ETH0.0008034117.23693882
Set Approval For...215266342025-01-01 2:29:1126 days ago1735698551IN
0x864D6DC0...E1178DAB7
0 ETH0.000163373.51144511
Set Approval For...215068852024-12-29 8:18:4729 days ago1735460327IN
0x864D6DC0...E1178DAB7
0 ETH0.000130292.80038046
Safe Transfer Fr...214883102024-12-26 18:03:5931 days ago1735236239IN
0x864D6DC0...E1178DAB7
0 ETH0.0004814810.34920492
Set Approval For...214135762024-12-16 7:26:4742 days ago1734334007IN
0x864D6DC0...E1178DAB7
0 ETH0.000389948.36613
Set Approval For...214009912024-12-14 13:15:5944 days ago1734182159IN
0x864D6DC0...E1178DAB7
0 ETH0.000218988.87063699
Set Approval For...213901272024-12-13 0:52:2345 days ago1734051143IN
0x864D6DC0...E1178DAB7
0 ETH0.0005996512.88860115
Safe Transfer Fr...213496462024-12-07 9:12:4751 days ago1733562767IN
0x864D6DC0...E1178DAB7
0 ETH0.0005477711.77696444
Safe Transfer Fr...213214112024-12-03 10:34:2355 days ago1733222063IN
0x864D6DC0...E1178DAB7
0 ETH0.0010069821.65005732
Set Approval For...213073492024-12-01 11:25:4757 days ago1733052347IN
0x864D6DC0...E1178DAB7
0 ETH0.0004968110.67825049
Set Approval For...212925232024-11-29 9:41:3559 days ago1732873295IN
0x864D6DC0...E1178DAB7
0 ETH0.000192547.82274641
Set Approval For...212795152024-11-27 13:53:4761 days ago1732715627IN
0x864D6DC0...E1178DAB7
0 ETH0.0006766614.54379796
Transfer From212243462024-11-19 21:03:3568 days ago1732050215IN
0x864D6DC0...E1178DAB7
0 ETH0.0008629619.97561693
Set Approval For...212075592024-11-17 12:54:4771 days ago1731848087IN
0x864D6DC0...E1178DAB7
0 ETH0.0004681510.06220332
Safe Transfer Fr...211966042024-11-16 0:14:4772 days ago1731716087IN
0x864D6DC0...E1178DAB7
0 ETH0.0008166417.55311206
Safe Transfer Fr...211428742024-11-08 12:18:3580 days ago1731068315IN
0x864D6DC0...E1178DAB7
0 ETH0.0007826416.82666539
Set Approval For...211377682024-11-07 19:09:5980 days ago1731006599IN
0x864D6DC0...E1178DAB7
0 ETH0.0010716523.03356716
View all transactions

Latest 21 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
187606712023-12-11 4:46:35413 days ago1702269995
0x864D6DC0...E1178DAB7
0.3725 ETH
187606572023-12-11 4:43:47413 days ago1702269827
0x864D6DC0...E1178DAB7
0.25 ETH
187568112023-12-10 15:49:35413 days ago1702223375
0x864D6DC0...E1178DAB7
0.2 ETH
187568052023-12-10 15:48:23413 days ago1702223303
0x864D6DC0...E1178DAB7
0.95 ETH
187497782023-12-09 16:11:35414 days ago1702138295
0x864D6DC0...E1178DAB7
1 ETH
187457782023-12-09 2:44:35415 days ago1702089875
0x864D6DC0...E1178DAB7
0.2 ETH
187431902023-12-08 18:00:59415 days ago1702058459
0x864D6DC0...E1178DAB7
1 ETH
187390252023-12-08 4:01:47416 days ago1702008107
0x864D6DC0...E1178DAB7
0.25 ETH
187390192023-12-08 4:00:35416 days ago1702008035
0x864D6DC0...E1178DAB7
0.3 ETH
187136742023-12-04 14:43:59420 days ago1701701039
0x864D6DC0...E1178DAB7
0.25 ETH
187136702023-12-04 14:43:11420 days ago1701700991
0x864D6DC0...E1178DAB7
0.25 ETH
187136662023-12-04 14:42:23420 days ago1701700943
0x864D6DC0...E1178DAB7
0.25 ETH
187023122023-12-03 0:30:47421 days ago1701563447
0x864D6DC0...E1178DAB7
0.2 ETH
187000182023-12-02 16:49:35421 days ago1701535775
0x864D6DC0...E1178DAB7
0.2 ETH
186998412023-12-02 16:13:59421 days ago1701533639
0x864D6DC0...E1178DAB7
0.25 ETH
186995692023-12-02 15:19:23422 days ago1701530363
0x864D6DC0...E1178DAB7
1.2 ETH
186968122023-12-02 6:04:47422 days ago1701497087
0x864D6DC0...E1178DAB7
0.2 ETH
186943722023-12-01 21:54:11422 days ago1701467651
0x864D6DC0...E1178DAB7
0.29 ETH
186934302023-12-01 18:44:23422 days ago1701456263
0x864D6DC0...E1178DAB7
0.3 ETH
186896252023-12-01 5:57:47423 days ago1701410267
0x864D6DC0...E1178DAB7
0.6 ETH
186894392023-12-01 5:20:23423 days ago1701408023
0x864D6DC0...E1178DAB7
0.5 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UndeadChef

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : UndeadChef.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// Contract by @AsteriaLabs
import "./Reg_ERC721Batch.sol";
import "./utils/ERC173.sol";
import "./interfaces/DefaultOperatorFilterer.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

/// @title Undead Chef
/// @author <@Suleman132446>
contract UndeadChef is
    Reg_ERC721Batch,
    ERC173,
    DefaultOperatorFilterer
{
    using MerkleProof for bytes32[];

    uint256 public whitelistPrice = 0.005 ether;
    uint256 public publicPrice = 0.005 ether;
    uint256 public maxPerWhitelist = 3;
    uint256 public maxPerPublic = 3;
    uint256 public maxSupply = 4000;

    
    error Whitelist_NOT_SET();
    error Whitelist_CONSUMED(address account);
    error Whitelist_FORBIDDEN(address account);

    bytes32 private _root;
    mapping(address => bool) private _private_consumed;
    mapping(address => bool) private _private_next;

    /**
     @dev An enum representing the sale state
     */
    enum Sale {
        PAUSED,
        PRIVATE,
        PRIVATE_NEXT,
        PUBLIC
    }

    Sale public saleState = Sale.PAUSED;
    // Mapping of nft minted by a wallet in public
    mapping(address => uint256) public mintedPerWallet;

    // Modifier to allow only owner

    // Modifier to check the sale state
    modifier isSaleState(Sale sale_) {
        require(saleState == sale_, "Sale not active");
        _;
    }

    // Modifier to block the other contracts
    modifier blockContracts() {
        require(tx.origin == msg.sender, "No smart contracts are allowed");
        _;
    }

    constructor(
        string memory name_,
        string memory symbol_,
        string memory baseURI_
    ) {
        __init_ERC721Metadata(name_, symbol_, baseURI_);
        _setOwner(msg.sender);
    }

    /**
     * @dev tranfer the funds from contract
     *
     * @param to_ : the address of the wallet to transfer the funds
     */
    function withdraw(address to_, uint amount_) public onlyOwner {
        uint256 _balance_ = address(this).balance;
        require(_balance_ > 0, "No balance to withdraw");
        require(amount_ <= _balance_, "Amount is not valid");
        address _recipient_ = payable(to_);
        (bool _success_, ) = _recipient_.call{value: amount_}("");
        require(_success_, "Transaction failed");
    }

    /**
     * @dev set the whiltelist price
     *
     * @param price_ : the price of whitelist mint
     */
    function setWhitelistPrice(uint256 price_) external onlyOwner {
        whitelistPrice = price_;
    }

    /**
     * @dev set the public mint price
     *
     * @param price_ : the price of public mint
     */
    function setPublicPrice(uint256 price_) external onlyOwner {
        publicPrice = price_;
    }

    /**
     * @dev set the mints per wallet in whitelist
     *
     * @param mints_ : the amount of for whitelist mint
     */
    function setMintsPerWhitelist(uint256 mints_) external onlyOwner {
        maxPerWhitelist = mints_;
    }

    /**
     * @dev set the mints per wallet in public
     *
     * @param mints_ : the amount of for public mint
     */
    function setMintsPerPublic(uint256 mints_) external onlyOwner {
        maxPerPublic = mints_;
    }

    /**
     * @dev set the max supply for collection
     *
     * @param supply_ : the amount for  supply
     */
    function setMaxSupply(uint256 supply_) external onlyOwner {
        uint _currentSupply_ = totalSupply();
        require(
            supply_ > _currentSupply_,
            "Max supply should be greater than current supply"
        );
        require(
            supply_ < maxSupply,
            "Max supply should be greater than previous max supply"
        );
        maxSupply = supply_;
    }

    /**
     * @dev set the merkle root for whitelist
     *
     * @param root_ : the merkle for whitelist
     */
    function setWhitelistRoot(bytes32 root_) external onlyOwner {
        _root = root_;
    }

    /**
     * @dev set the base uri for collection
     *
     * @param baseURI_ : the base uri for collection
     */
    function setBaseURI(string memory baseURI_) external onlyOwner {
        _setBaseURI(baseURI_);
    }

    /**
     * @dev set the sale state
     *
     * @param sale_ : the new sale state
     */
    function setSaleState(Sale sale_) external onlyOwner {
        saleState = sale_;
    }


    function mintWhitelist(bytes32[] memory proof_)
        external
        payable
        blockContracts
        isSaleState(Sale.PRIVATE)
    {
        if (_root == 0) {
            revert Whitelist_NOT_SET();
        }
        address account_ = msg.sender;
        if (_private_consumed[account_]) {
            revert Whitelist_CONSUMED(account_);
        }
        bytes32 leaf = keccak256(abi.encodePacked(account_));
        bool isAllowed =  MerkleProof.processProof(proof_, leaf) == _root;
        if (!isAllowed) {
            revert Whitelist_FORBIDDEN(account_);
        }
        uint _supply_ = totalSupply();
        require(_supply_ + maxPerWhitelist <= maxSupply, "Exceeds supply");
        require(
            msg.value == whitelistPrice,
            "Ether sent is not correct"
        );
        _mint(msg.sender, maxPerWhitelist);
       _private_consumed[account_] = true;
    }

    function mintNextWhitelist(bytes32[] memory proof_)
        external
        payable
        blockContracts
        isSaleState(Sale.PRIVATE_NEXT)
    {
        if (_root == 0) {
            revert Whitelist_NOT_SET();
        }
        address account_ = msg.sender;
        if (_private_next[account_]) {
            revert Whitelist_CONSUMED(account_);
        }
        bytes32 leaf = keccak256(abi.encodePacked(account_));
        bool isAllowed =  MerkleProof.processProof(proof_, leaf) == _root;
        if (!isAllowed) {
            revert Whitelist_FORBIDDEN(account_);
        }
        uint _supply_ = totalSupply();
        require(_supply_ + maxPerWhitelist <= maxSupply, "Exceeds supply");
        require(
            msg.value == whitelistPrice,
            "Ether sent is not correct"
        );
        _mint(msg.sender, maxPerWhitelist);
       _private_next[account_] = true;
    }

    /**
     * @dev mint the token for airdrop
     *
     * @param qty_ : the quantity of mint
     * @param to_: the address to send to
     */
    function airdrop( uint256 qty_ , address to_) onlyOwner
        external
        payable
        blockContracts
    {
        uint _supply_ = totalSupply();
        require(_supply_ + qty_ <= maxSupply, "Exceeds supply");
        _mint(to_, qty_);
    }

    /**
     * @dev mint the token in public sale
     *
     * @param qty_ : the quantity of mint
     */
    function mintPublic(uint256 qty_)
        external
        payable
        blockContracts
        isSaleState(Sale.PUBLIC)
    {
        uint _supply_ = totalSupply();
        require(
            mintedPerWallet[msg.sender] + qty_ <= maxPerPublic,
            "Exceeds mint per wallet"
        );
        require(_supply_ + qty_ <= maxSupply, "Exceeds supply");
        require(msg.value == qty_ * publicPrice, "Ether sent is not correct");
        _mint(msg.sender, qty_);
        mintedPerWallet[msg.sender] += qty_;
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

File 2 of 14 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 3 of 14 : DefaultOperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {OperatorFilterer} from "./OperatorFilterer.sol";

abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

File 4 of 14 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

interface IERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

File 5 of 14 : IERC173.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/**
* @dev Required interface of an ERC173 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-173[EIP].
*/
interface IERC173 /* is IERC165 */ {
    /// @dev This emits when ownership of a contract changes.    
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Get the address of the owner    
    /// @return The address of the owner.
    function owner() view external returns(address);
	
    /// @notice Set the address of the new owner of the contract
    /// @dev Set _newOwner to address(0) to renounce any ownership.
    /// @param _newOwner The address of the new owner of the contract    
    function transferOwnership(address _newOwner) external;	
}

File 6 of 14 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)

pragma solidity 0.8.17;

/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface IERC721 /* is IERC165 */ {
  /// @dev This emits when ownership of any NFT changes by any mechanism.
  ///  This event emits when NFTs are created (`from` == 0) and destroyed
  ///  (`to` == 0). Exception: during contract creation, any number of NFTs
  ///  may be created and assigned without emitting Transfer. At the time of
  ///  any transfer, the approved address for that NFT (if any) is reset to none.
  event Transfer( address indexed from_, address indexed to_, uint256 indexed tokenId_ );

  /// @dev This emits when the approved address for an NFT is changed or
  ///  reaffirmed. The zero address indicates there is no approved address.
  ///  When a Transfer event emits, this also indicates that the approved
  ///  address for that NFT (if any) is reset to none.
  event Approval( address indexed owner_, address indexed approved_, uint256 indexed tokenId_ );

  /// @dev This emits when an operator is enabled or disabled for an owner.
  ///  The operator can manage all NFTs of the owner.
  event ApprovalForAll( address indexed owner_, address indexed operator_, bool approved_ );

  /// @notice Count all NFTs assigned to an owner
  /// @dev NFTs assigned to the zero address are considered invalid, and this
  ///  function throws for queries about the zero address.
  /// @param owner_ An address for whom to query the balance
  /// @return The number of NFTs owned by `owner_`, possibly zero
  function balanceOf( address owner_ ) external view returns ( uint256 );

  /// @notice Find the owner of an NFT
  /// @dev NFTs assigned to zero address are considered invalid, and queries
  ///  about them do throw.
  /// @param tokenId_ The identifier for an NFT
  /// @return The address of the owner of the NFT
  function ownerOf( uint256 tokenId_ ) external view returns ( address );

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev Throws unless `msg.sender` is the current owner, an authorized
  ///  operator, or the approved address for this NFT. Throws if `from_` is
  ///  not the current owner. Throws if `to_` is the zero address. Throws if
  ///  `tokenId_` is not a valid NFT. When transfer is complete, this function
  ///  checks if `to_` is a smart contract (code size > 0). If so, it calls
  ///  `onERC721Received` on `to_` and throws if the return value is not
  ///  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
  /// @param from_ The current owner of the NFT
  /// @param to_ The new owner
  /// @param tokenId_ The NFT to transfer
  /// @param data_ Additional data with no specified format, sent in call to `to_`
  function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes calldata data_ ) external;

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev This works identically to the other function with an extra data parameter,
  ///  except this function just sets data to "".
  /// @param from_ The current owner of the NFT
  /// @param to_ The new owner
  /// @param tokenId_ The NFT to transfer
  function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) external;

  /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
  ///  TO CONFIRM THAT `to_` IS CAPABLE OF RECEIVING NFTS OR ELSE
  ///  THEY MAY BE PERMANENTLY LOST
  /// @dev Throws unless `msg.sender` is the current owner, an authorized
  ///  operator, or the approved address for this NFT. Throws if `from_` is
  ///  not the current owner. Throws if `to_` is the zero address. Throws if
  ///  `tokenId_` is not a valid NFT.
  /// @param from_ The current owner of the NFT
  /// @param to_ The new owner
  /// @param tokenId_ The NFT to transfer
  function transferFrom( address from_, address to_, uint256 tokenId_ ) external;

  /// @notice Change or reaffirm the approved address for an NFT
  /// @dev The zero address indicates there is no approved address.
  ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
  ///  operator of the current owner.
  /// @param approved_ The new approved NFT controller
  /// @param tokenId_ The NFT to approve
  function approve( address approved_, uint256 tokenId_ ) external;

  /// @notice Enable or disable approval for a third party ("operator") to manage
  ///  all of `msg.sender`'s assets
  /// @dev Emits the ApprovalForAll event. The contract MUST allow
  ///  multiple operators per owner.
  /// @param operator_ Address to add to the set of authorized operators
  /// @param approved_ True if the operator is approved, false to revoke approval
  function setApprovalForAll( address operator_, bool approved_ ) external;

  /// @notice Get the approved address for a single NFT
  /// @dev Throws if `tokenId_` is not a valid NFT.
  /// @param tokenId_ The NFT to find the approved address for
  /// @return The approved address for this NFT, or the zero address if there is none
  function getApproved( uint256 tokenId_ ) external view returns ( address );

  /// @notice Query if an address is an authorized operator for another address
  /// @param owner_ The address that owns the NFTs
  /// @param operator_ The address that acts on behalf of the owner
  /// @return True if `operator_` is an approved operator for `owner_`, false otherwise
  function isApprovedForAll( address owner_, address operator_ ) external view returns ( bool );
}

File 7 of 14 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x780e9d63.
interface IERC721Enumerable /* is IERC721 */ {
    /// @notice Count NFTs tracked by this contract
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function totalSupply() external view returns ( uint256 );

    /// @notice Enumerate valid NFTs
    /// @dev Throws if `index_` >= `totalSupply()`.
    /// @param index_ A counter less than `totalSupply()`
    /// @return The token identifier for the `index_`th NFT,
    ///  (sort order not specified)
    function tokenByIndex( uint256 index_ ) external view returns ( uint256 );

    /// @notice Enumerate NFTs assigned to an owner
    /// @dev Throws if `index_` >= `balanceOf(owner_)` or if
    ///  `owner_` is the zero address, representing invalid NFTs.
    /// @param owner_ An address where we are interested in NFTs owned by them
    /// @param index_ A counter less than `balanceOf(owner_)`
    /// @return The token identifier for the `index_`th NFT assigned to `owner_`,
    ///   (sort order not specified)
    function tokenOfOwnerByIndex( address owner_, uint256 index_ ) external view returns ( uint256 );
}

File 8 of 14 : IERC721Errors.sol
// SPDX-License-Identifier: MIT

/**
* Author: Lambdalf the White
*/

pragma solidity 0.8.17;

interface IERC721Errors {
  /**
  * @dev Thrown when `operator` has not been approved to manage `tokenId` on behalf of `tokenOwner`.
  * 
  * @param tokenOwner : address owning the token
  * @param operator   : address trying to manage the token
  * @param tokenId    : identifier of the NFT being referenced
  */
  error IERC721_CALLER_NOT_APPROVED( address tokenOwner, address operator, uint256 tokenId );
  /**
  * @dev Thrown when `operator` tries to approve themselves for managing a token they own.
  * 
  * @param operator : address that is trying to approve themselves
  */
  error IERC721_INVALID_APPROVAL( address operator );
  /**
  * @dev Thrown when a token is being transferred to the zero address.
  */
  error IERC721_INVALID_TRANSFER();
  /**
  * @dev Thrown when a token is being transferred from an address that doesn't own it.
  * 
  * @param tokenOwner : address owning the token
  * @param from       : address that the NFT is being transferred from
  * @param tokenId    : identifier of the NFT being referenced
  */
  error IERC721_INVALID_TRANSFER_FROM( address tokenOwner, address from, uint256 tokenId );
  /**
  * @dev Thrown when the requested token doesn't exist.
  * 
  * @param tokenId : identifier of the NFT being referenced
  */
  error IERC721_NONEXISTANT_TOKEN( uint256 tokenId );
  /**
  * @dev Thrown when a token is being safely transferred to a contract unable to handle it.
  * 
  * @param receiver : address unable to receive the token
  */
  error IERC721_NON_ERC721_RECEIVER( address receiver );
  /**
  * @dev Thrown when trying to get the token at an index that doesn't exist.
  * 
  * @param index : the inexistant index
  */
  error IERC721Enumerable_INDEX_OUT_OF_BOUNDS( uint256 index );
  /**
  * @dev Thrown when trying to get the token owned by `tokenOwner` at an index that doesn't exist.
  * 
  * @param tokenOwner : address owning the token
  * @param index      : the inexistant index
  */
  error IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS( address tokenOwner, uint256 index );
}

File 9 of 14 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface IERC721Metadata /* is IERC721 */ {
    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns ( string memory _name );

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns ( string memory _symbol );

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI( uint256 _tokenId ) external view returns ( string memory );
}

File 10 of 14 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface IERC721Receiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The ERC721 smart contract calls this function on the recipient
    ///  after a `transfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param operator_ The address which called `safeTransferFrom` function
    /// @param from_ The address which previously owned the token
    /// @param tokenId_ The NFT identifier which is being transferred
    /// @param data_ Additional data with no specified format
    /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onERC721Received( address operator_, address from_, uint256 tokenId_, bytes calldata data_ ) external returns( bytes4 );
}

File 11 of 14 : IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator)
        external
        view
        returns (bool);

    function register(address registrant) external;

    function registerAndSubscribe(address registrant, address subscription)
        external;

    function registerAndCopyEntries(
        address registrant,
        address registrantToCopy
    ) external;

    function updateOperator(
        address registrant,
        address operator,
        bool filtered
    ) external;

    function updateOperators(
        address registrant,
        address[] calldata operators,
        bool filtered
    ) external;

    function updateCodeHash(
        address registrant,
        bytes32 codehash,
        bool filtered
    ) external;

    function updateCodeHashes(
        address registrant,
        bytes32[] calldata codeHashes,
        bool filtered
    ) external;

    function subscribe(address registrant, address registrantToSubscribe)
        external;

    function unsubscribe(address registrant, bool copyExistingEntries) external;

    function subscriptionOf(address addr) external returns (address registrant);

    function subscribers(address registrant)
        external
        returns (address[] memory);

    function subscriberAt(address registrant, uint256 index)
        external
        returns (address);

    function copyEntriesOf(address registrant, address registrantToCopy)
        external;

    function isOperatorFiltered(address registrant, address operator)
        external
        returns (bool);

    function isCodeHashOfFiltered(address registrant, address operatorWithCode)
        external
        returns (bool);

    function isCodeHashFiltered(address registrant, bytes32 codeHash)
        external
        returns (bool);

    function filteredOperators(address addr)
        external
        returns (address[] memory);

    function filteredCodeHashes(address addr)
        external
        returns (bytes32[] memory);

    function filteredOperatorAt(address registrant, uint256 index)
        external
        returns (address);

    function filteredCodeHashAt(address registrant, uint256 index)
        external
        returns (bytes32);

    function isRegistered(address addr) external returns (bool);

    function codeHashOf(address addr) external returns (bytes32);
}

File 12 of 14 : OperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";

abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry constant operatorFilterRegistry =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(operatorFilterRegistry).code.length > 0) {
            if (subscribe) {
                operatorFilterRegistry.registerAndSubscribe(
                    address(this),
                    subscriptionOrRegistrantToCopy
                );
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    operatorFilterRegistry.registerAndCopyEntries(
                        address(this),
                        subscriptionOrRegistrantToCopy
                    );
                } else {
                    operatorFilterRegistry.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(operatorFilterRegistry).code.length > 0) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (
                !(operatorFilterRegistry.isOperatorAllowed(
                    address(this),
                    msg.sender
                ) &&
                    operatorFilterRegistry.isOperatorAllowed(
                        address(this),
                        from
                    ))
            ) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }
}

File 13 of 14 : Reg_ERC721Batch.sol
// SPDX-License-Identifier: MIT

/**
 * Author: Lambdalf the White
 */

pragma solidity 0.8.17;

import "./interfaces/IERC721Errors.sol";
import "./interfaces/IERC165.sol";
import "./interfaces/IERC721.sol";
import "./interfaces/IERC721Enumerable.sol";
import "./interfaces/IERC721Metadata.sol";
import "./interfaces/IERC721Receiver.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 * This contract features:
 * ~ Very Cheap batch minting
 * ~ Token tracker support
 *
 * Note: This implementation imposes a very expensive `balanceOf()` and `ownerOf()`.
 * It is not recommended to interract with those from another contract.
 */
abstract contract Reg_ERC721Batch is
    IERC721Errors,
    IERC165,
    IERC721,
    IERC721Metadata,
    IERC721Enumerable
{
    uint256 private _nextId = 1;
    string public name;
    string public symbol;

    // Mapping from token ID to approved address
    mapping(uint256 => address) public getApproved;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    // List of owner addresses
    mapping(uint256 => address) private _owners;

    // Token Base URI
    string private _baseURI;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __init_ERC721Metadata(
        string memory name_,
        string memory symbol_,
        string memory baseURI_
    ) internal {
        name = name_;
        symbol = symbol_;
        _baseURI = baseURI_;
    }

    // **************************************
    // *****          MODIFIER          *****
    // **************************************
    /**
     * @dev Ensures the token exist.
     * A token exists if it has been minted and is not owned by the null address.
     *
     * @param tokenId_ : identifier of the NFT being referenced
     */
    modifier exists(uint256 tokenId_) {
        if (!_exists(tokenId_)) {
            revert IERC721_NONEXISTANT_TOKEN(tokenId_);
        }
        _;
    }

    // **************************************

    // **************************************
    // *****          INTERNAL          *****
    // **************************************
    /**
     * @dev Internal function returning the number of tokens in `tokenOwner_`'s account.
     */
    function _balanceOf(address tokenOwner_)
        internal
        view
        virtual
        returns (uint256)
    {
        if (tokenOwner_ == address(0)) {
            return 0;
        }

        uint256 _count_ = 0;
        address _currentTokenOwner_;
        for (uint256 i = 1; i < _nextId; ++i) {
            if (_exists(i)) {
                if (_owners[i] != address(0)) {
                    _currentTokenOwner_ = _owners[i];
                }
                if (tokenOwner_ == _currentTokenOwner_) {
                    _count_++;
                }
            }
        }
        return _count_;
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from_ address representing the previous owner of the given token ID
     * @param to_ target address that will receive the tokens
     * @param tokenId_ uint256 ID of the token to be transferred
     * @param data_ bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) internal virtual returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.
        //
        // IMPORTANT
        // It is unsafe to assume that an address not flagged by this method
        // is an externally-owned account (EOA) and not a contract.
        //
        // Among others, the following types of addresses will not be flagged:
        //
        //  - an externally-owned account
        //  - a contract in construction
        //  - an address where a contract will be created
        //  - an address where a contract lived, but was destroyed
        uint256 _size_;
        assembly {
            _size_ := extcodesize(to_)
        }

        // If address is a contract, check that it is aware of how to handle ERC721 tokens
        if (_size_ > 0) {
            try
                IERC721Receiver(to_).onERC721Received(
                    msg.sender,
                    from_,
                    tokenId_,
                    data_
                )
            returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert IERC721_NON_ERC721_RECEIVER(to_);
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Internal function returning whether a token exists.
     * A token exists if it has been minted and is not owned by the null address.
     *
     * @param tokenId_ uint256 ID of the token to verify
     *
     * @return bool whether the token exists
     */
    function _exists(uint256 tokenId_) internal view virtual returns (bool) {
        if (tokenId_ == 0) {
            return false;
        }
        return tokenId_ < _nextId;
    }

    /**
     * @dev Internal function returning whether `operator_` is allowed
     * to manage tokens on behalf of `tokenOwner_`.
     *
     * @param tokenOwner_ address that owns tokens
     * @param operator_ address that tries to manage tokens
     *
     * @return bool whether `operator_` is allowed to handle the token
     */
    function _isApprovedForAll(address tokenOwner_, address operator_)
        internal
        view
        virtual
        returns (bool)
    {
        return _operatorApprovals[tokenOwner_][operator_];
    }

    /**
     * @dev Internal function returning whether `operator_` is allowed to handle `tokenId_`
     *
     * Note: To avoid multiple checks for the same data, it is assumed that existence of `tokeId_`
     * has been verified prior via {_exists}
     * If it hasn't been verified, this function might panic
     *
     * @param operator_ address that tries to handle the token
     * @param tokenId_ uint256 ID of the token to be handled
     *
     * @return bool whether `operator_` is allowed to handle the token
     */
    function _isApprovedOrOwner(
        address tokenOwner_,
        address operator_,
        uint256 tokenId_
    ) internal view virtual returns (bool) {
        bool _isApproved_ = operator_ == tokenOwner_ ||
            operator_ == getApproved[tokenId_] ||
            _isApprovedForAll(tokenOwner_, operator_);
        return _isApproved_;
    }

    /**
     * @dev Mints `qty_` tokens and transfers them to `to_`.
     *
     * This internal function can be used to perform token minting.
     *
     * Emits one or more {Transfer} event.
     */
    function _mint(address to_, uint256 qty_) internal virtual {
        uint256 _firstToken_ = _nextId;
        uint256 _nextStart_ = _firstToken_ + qty_;
        uint256 _lastToken_ = _nextStart_ - 1;

        _owners[_firstToken_] = to_;
        if (_lastToken_ > _firstToken_) {
            _owners[_lastToken_] = to_;
        }
        _nextId = _nextStart_;

        if (!_checkOnERC721Received(address(0), to_, _firstToken_, "")) {
            revert IERC721_NON_ERC721_RECEIVER(to_);
        }

        for (uint256 i = _firstToken_; i < _nextStart_; ++i) {
            emit Transfer(address(0), to_, i);
        }
    }

    /**
     * @dev Internal function returning the owner of the `tokenId_` token.
     *
     * @param tokenId_ uint256 ID of the token to verify
     *
     * @return address the address of the token owner
     */
    function _ownerOf(uint256 tokenId_)
        internal
        view
        virtual
        returns (address)
    {
        uint256 _tokenId_ = tokenId_;
        address _tokenOwner_ = _owners[_tokenId_];
        while (_tokenOwner_ == address(0)) {
            _tokenId_--;
            _tokenOwner_ = _owners[_tokenId_];
        }

        return _tokenOwner_;
    }

    /**
     * @dev Internal function used to set the base URI of the collection.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
     * @dev Internal function returning the total supply.
     */
    function _totalSupply() internal view virtual returns (uint256) {
        return supplyMinted();
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function _toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Transfers `tokenId_` from `from_` to `to_`.
     *
     * This internal function can be used to implement alternative mechanisms to perform
     * token transfer, such as signature-based, or token burning.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from_,
        address to_,
        uint256 tokenId_
    ) internal virtual {
        getApproved[tokenId_] = address(0);
        uint256 _previousId_ = tokenId_ > 1 ? tokenId_ - 1 : 1;
        uint256 _nextId_ = tokenId_ + 1;
        bool _previousShouldUpdate_ = _previousId_ < tokenId_ &&
            _exists(_previousId_) &&
            _owners[_previousId_] == address(0);
        bool _nextShouldUpdate_ = _exists(_nextId_) &&
            _owners[_nextId_] == address(0);

        if (_previousShouldUpdate_) {
            _owners[_previousId_] = from_;
        }

        if (_nextShouldUpdate_) {
            _owners[_nextId_] = from_;
        }

        _owners[tokenId_] = to_;

        emit Transfer(from_, to_, tokenId_);
    }

    // **************************************

    // **************************************
    // *****           PUBLIC           *****
    // **************************************
    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to_, uint256 tokenId_)
        public
        virtual
        exists(tokenId_)
    {
        address _operator_ = msg.sender;
        address _tokenOwner_ = _ownerOf(tokenId_);
        if (to_ == _tokenOwner_) {
            revert IERC721_INVALID_APPROVAL(to_);
        }

        bool _isApproved_ = _isApprovedOrOwner(
            _tokenOwner_,
            _operator_,
            tokenId_
        );
        if (!_isApproved_) {
            revert IERC721_CALLER_NOT_APPROVED(
                _tokenOwner_,
                _operator_,
                tokenId_
            );
        }

        getApproved[tokenId_] = to_;
        emit Approval(_tokenOwner_, to_, tokenId_);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     *
     * Note: We can ignore `from_` as we can compare everything to the actual token owner,
     * but we cannot remove this parameter to stay in conformity with IERC721
     */
    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public virtual override {
        safeTransferFrom(from_, to_, tokenId_, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     *
     * Note: We can ignore `from_` as we can compare everything to the actual token owner,
     * but we cannot remove this parameter to stay in conformity with IERC721
     */
    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) public virtual override {
        transferFrom(from_, to_, tokenId_);
        if (!_checkOnERC721Received(from_, to_, tokenId_, data_)) {
            revert IERC721_NON_ERC721_RECEIVER(to_);
        }
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator_, bool approved_)
        public
        virtual
        override
    {
        address _account_ = msg.sender;
        if (operator_ == _account_) {
            revert IERC721_INVALID_APPROVAL(operator_);
        }

        _operatorApprovals[_account_][operator_] = approved_;
        emit ApprovalForAll(_account_, operator_, approved_);
    }

    /**
     * @dev See {IERC721-transferFrom}.
     *
     * Note: We can ignore `from_` as we can compare everything to the actual token owner,
     * but we cannot remove this parameter to stay in conformity with IERC721
     */
    function transferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public virtual exists(tokenId_) {
        if (to_ == address(0)) {
            revert IERC721_INVALID_TRANSFER();
        }

        address _operator_ = msg.sender;
        address _tokenOwner_ = _ownerOf(tokenId_);
        if (from_ != _tokenOwner_) {
            revert IERC721_INVALID_TRANSFER_FROM(_tokenOwner_, from_, tokenId_);
        }

        bool _isApproved_ = _isApprovedOrOwner(
            _tokenOwner_,
            _operator_,
            tokenId_
        );
        if (!_isApproved_) {
            revert IERC721_CALLER_NOT_APPROVED(
                _tokenOwner_,
                _operator_,
                tokenId_
            );
        }

        _transfer(_tokenOwner_, to_, tokenId_);
    }

    // **************************************

    // **************************************
    // *****            VIEW            *****
    // **************************************
    /**
     * @dev Returns the number of tokens in `tokenOwner_`'s account.
     */
    function balanceOf(address tokenOwner_)
        public
        view
        virtual
        returns (uint256)
    {
        return _balanceOf(tokenOwner_);
    }

    /**
     * @dev Returns if the `operator_` is allowed to manage all of the assets of `tokenOwner_`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address tokenOwner_, address operator_)
        public
        view
        virtual
        returns (bool)
    {
        return _isApprovedForAll(tokenOwner_, operator_);
    }

    /**
     * @dev Returns the owner of the `tokenId_` token.
     *
     * Requirements:
     *
     * - `tokenId_` must exist.
     */
    function ownerOf(uint256 tokenId_)
        public
        view
        virtual
        exists(tokenId_)
        returns (address)
    {
        return _ownerOf(tokenId_);
    }

    /**
     * @dev Returns the total number of tokens minted
     *
     * @return uint256 the number of tokens that have been minted so far
     */
    function supplyMinted() public view virtual returns (uint256) {
        return _nextId - 1;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId_)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId_ == type(IERC721Enumerable).interfaceId ||
            interfaceId_ == type(IERC721Metadata).interfaceId ||
            interfaceId_ == type(IERC721).interfaceId ||
            interfaceId_ == type(IERC165).interfaceId;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index_)
        public
        view
        virtual
        override
        returns (uint256)
    {
        if (index_ >= supplyMinted()) {
            revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS(index_);
        }
        return index_ + 1;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address tokenOwner_, uint256 index_)
        public
        view
        virtual
        override
        returns (uint256 tokenId)
    {
        if (index_ >= _balanceOf(tokenOwner_)) {
            revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS(
                tokenOwner_,
                index_
            );
        }

        uint256 _count_ = 0;
        for (uint256 i = 1; i < _nextId; i++) {
            if (_exists(i) && tokenOwner_ == _ownerOf(i)) {
                if (index_ == _count_) {
                    return i;
                }
                _count_++;
            }
        }
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId_)
        public
        view
        virtual
        override
        exists(tokenId_)
        returns (string memory)
    {
        return
            bytes(_baseURI).length > 0
                ? string(abi.encodePacked(_baseURI, _toString(tokenId_)))
                : _toString(tokenId_);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply();
    }
    // **************************************
}

File 14 of 14 : ERC173.sol
// SPDX-License-Identifier: MIT

/**
* Author: Lambdalf the White
*/

pragma solidity 0.8.17;

import "../interfaces/IERC173.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.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract ERC173 is IERC173 {
	// Errors
  /**
  * @dev Thrown when `operator` is not the contract owner.
  * 
  * @param operator : address trying to use a function reserved to contract owner without authorization
  */
  error IERC173_NOT_OWNER( address operator );

	// The owner of the contract
	address private _owner;

	/**
	* @dev Throws if called by any account other than the owner.
	*/
	modifier onlyOwner() {
		address _sender_ = msg.sender;
		if ( owner() != _sender_ ) {
			revert IERC173_NOT_OWNER( _sender_ );
		}
		_;
	}

	/**
	* @dev Sets the contract owner.
	* 
	* Note: This function needs to be called in the contract constructor to initialize the contract owner, 
	* if it is not, then parts of the contract might be non functional
	* 
	* @param owner_ : address that owns the contract
	*/
	function _setOwner( address owner_ ) internal {
		_owner = owner_;
	}

	/**
	* @dev Returns the address of the current contract owner.
	* 
	* @return address : the current contract owner
	*/
	function owner() public view virtual returns ( address ) {
		return _owner;
	}

	/**
	* @dev Transfers ownership of the contract to `newOwner_`.
	* 
	* @param newOwner_ : address of the new contract owner
	* 
	* Requirements:
	* 
  * - Caller must be the contract owner.
	*/
	function transferOwnership( address newOwner_ ) public virtual onlyOwner {
		address _oldOwner_ = _owner;
		_owner = newOwner_;
		emit OwnershipTransferred( _oldOwner_, newOwner_ );
	}
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"baseURI_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"IERC173_NOT_OWNER","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_CALLER_NOT_APPROVED","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"IERC721_INVALID_APPROVAL","type":"error"},{"inputs":[],"name":"IERC721_INVALID_TRANSFER","type":"error"},{"inputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_INVALID_TRANSFER_FROM","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_NONEXISTANT_TOKEN","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"IERC721_NON_ERC721_RECEIVER","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Whitelist_CONSUMED","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Whitelist_FORBIDDEN","type":"error"},{"inputs":[],"name":"Whitelist_NOT_SET","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":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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"},{"inputs":[{"internalType":"uint256","name":"qty_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"airdrop","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerPublic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPerWhitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"mintNextWhitelist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"qty_","type":"uint256"}],"name":"mintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"mintWhitelist","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintedPerWallet","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":"publicPrice","outputs":[{"internalType":"uint256","name":"","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":"nonpayable","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":"nonpayable","type":"function"},{"inputs":[],"name":"saleState","outputs":[{"internalType":"enum UndeadChef.Sale","name":"","type":"uint8"}],"stateMutability":"view","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":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"supply_","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mints_","type":"uint256"}],"name":"setMintsPerPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mints_","type":"uint256"}],"name":"setMintsPerWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"name":"setPublicPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum UndeadChef.Sale","name":"sale_","type":"uint8"}],"name":"setSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"name":"setWhitelistPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root_","type":"bytes32"}],"name":"setWhitelistRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"index_","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"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":"","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":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260016000556611c37937e080006008556611c37937e080006009556003600a556003600b55610fa0600c556000601060006101000a81548160ff021916908360038111156200005857620000576200034a565b5b02179055503480156200006a57600080fd5b50604051620057d6380380620057d683398181016040528101906200009091906200050c565b733cc6cdda760b79bafa08df41ecfa224f810dceb6600160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156200029c57801562000162576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401620001289291906200060a565b600060405180830381600087803b1580156200014357600080fd5b505af115801562000158573d6000803e3d6000fd5b505050506200029b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146200021c576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b8152600401620001e29291906200060a565b600060405180830381600087803b158015620001fd57600080fd5b505af115801562000212573d6000803e3d6000fd5b505050506200029a565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000265919062000637565b600060405180830381600087803b1580156200028057600080fd5b505af115801562000295573d6000803e3d6000fd5b505050505b5b5b5050620002b1838383620002cb60201b60201c565b620002c2336200030660201b60201c565b50505062000986565b8260019081620002dc91906200089f565b508160029081620002ee91906200089f565b5080600690816200030091906200089f565b50505050565b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620003e28262000397565b810181811067ffffffffffffffff82111715620004045762000403620003a8565b5b80604052505050565b60006200041962000379565b9050620004278282620003d7565b919050565b600067ffffffffffffffff8211156200044a5762000449620003a8565b5b620004558262000397565b9050602081019050919050565b60005b838110156200048257808201518184015260208101905062000465565b60008484015250505050565b6000620004a56200049f846200042c565b6200040d565b905082815260208101848484011115620004c457620004c362000392565b5b620004d184828562000462565b509392505050565b600082601f830112620004f157620004f06200038d565b5b8151620005038482602086016200048e565b91505092915050565b60008060006060848603121562000528576200052762000383565b5b600084015167ffffffffffffffff81111562000549576200054862000388565b5b6200055786828701620004d9565b935050602084015167ffffffffffffffff8111156200057b576200057a62000388565b5b6200058986828701620004d9565b925050604084015167ffffffffffffffff811115620005ad57620005ac62000388565b5b620005bb86828701620004d9565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005f282620005c5565b9050919050565b6200060481620005e5565b82525050565b6000604082019050620006216000830185620005f9565b620006306020830184620005f9565b9392505050565b60006020820190506200064e6000830184620005f9565b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620006a757607f821691505b602082108103620006bd57620006bc6200065f565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620007277fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620006e8565b620007338683620006e8565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620007806200077a62000774846200074b565b62000755565b6200074b565b9050919050565b6000819050919050565b6200079c836200075f565b620007b4620007ab8262000787565b848454620006f5565b825550505050565b600090565b620007cb620007bc565b620007d881848462000791565b505050565b5b818110156200080057620007f4600082620007c1565b600181019050620007de565b5050565b601f8211156200084f576200081981620006c3565b6200082484620006d8565b8101602085101562000834578190505b6200084c6200084385620006d8565b830182620007dd565b50505b505050565b600082821c905092915050565b6000620008746000198460080262000854565b1980831691505092915050565b60006200088f838362000861565b9150826002028217905092915050565b620008aa8262000654565b67ffffffffffffffff811115620008c657620008c5620003a8565b5b620008d282546200068e565b620008df82828562000804565b600060209050601f83116001811462000917576000841562000902578287015190505b6200090e858262000881565b8655506200097e565b601f1984166200092786620006c3565b60005b8281101562000951578489015182556001820191506020850194506020810190506200092a565b868310156200097157848901516200096d601f89168262000861565b8355505b6001600288020188555050505b505050505050565b614e4080620009966000396000f3fe6080604052600436106102305760003560e01c806370a082311161012e578063c87b56dd116100ab578063efd0cbf91161006f578063efd0cbf914610848578063f2fde38b14610864578063f3fef3a31461088d578063f5aa406d146108b6578063fc1a1c36146108df57610230565b8063c87b56dd1461074f578063c95d83c61461078c578063cfe1908d146107b5578063d5abeb01146107e0578063e985e9c51461080b57610230565b8063a22cb465116100f2578063a22cb4651461068d578063a945bf80146106b6578063b88d4fde146106e1578063bc63f02e1461070a578063c62752551461072657610230565b806370a08231146105a6578063717d57d3146105e35780637e9845f51461060c5780638da5cb5b1461063757806395d89b411461066257610230565b80633a602b4d116101bc5780635a67de07116101805780635a67de07146104c1578063603f4d52146104ea5780636352211e1461051557806366cc5f0d146105525780636f8b44b01461057d57610230565b80633a602b4d146103d957806342842e0e1461041657806344d843811461043f5780634f6ccce71461045b57806355f804b31461049857610230565b8063095ea7b311610203578063095ea7b31461030357806318160ddd1461032c57806323b872dd1461035757806328bb1a2e146103805780632f745c591461039c57610230565b806301ffc9a71461023557806302c366bc1461027257806306fdde031461029b578063081812fc146102c6575b600080fd5b34801561024157600080fd5b5061025c60048036038101906102579190613894565b61090a565b60405161026991906138dc565b60405180910390f35b34801561027e57600080fd5b506102996004803603810190610294919061392d565b610aac565b005b3480156102a757600080fd5b506102b0610b33565b6040516102bd91906139ea565b60405180910390f35b3480156102d257600080fd5b506102ed60048036038101906102e8919061392d565b610bc1565b6040516102fa9190613a4d565b60405180910390f35b34801561030f57600080fd5b5061032a60048036038101906103259190613a94565b610bf4565b005b34801561033857600080fd5b50610341610dcb565b60405161034e9190613ae3565b60405180910390f35b34801561036357600080fd5b5061037e60048036038101906103799190613afe565b610dda565b005b61039a60048036038101906103959190613ccf565b610fbc565b005b3480156103a857600080fd5b506103c360048036038101906103be9190613a94565b611300565b6040516103d09190613ae3565b60405180910390f35b3480156103e557600080fd5b5061040060048036038101906103fb9190613d18565b6113eb565b60405161040d9190613ae3565b60405180910390f35b34801561042257600080fd5b5061043d60048036038101906104389190613afe565b611403565b005b61045960048036038101906104549190613ccf565b6115e5565b005b34801561046757600080fd5b50610482600480360381019061047d919061392d565b611929565b60405161048f9190613ae3565b60405180910390f35b3480156104a457600080fd5b506104bf60048036038101906104ba9190613dfa565b61198a565b005b3480156104cd57600080fd5b506104e860048036038101906104e39190613e68565b611a13565b005b3480156104f657600080fd5b506104ff611abd565b60405161050c9190613f0c565b60405180910390f35b34801561052157600080fd5b5061053c6004803603810190610537919061392d565b611ad0565b6040516105499190613a4d565b60405180910390f35b34801561055e57600080fd5b50610567611b2e565b6040516105749190613ae3565b60405180910390f35b34801561058957600080fd5b506105a4600480360381019061059f919061392d565b611b34565b005b3480156105b257600080fd5b506105cd60048036038101906105c89190613d18565b611c4e565b6040516105da9190613ae3565b60405180910390f35b3480156105ef57600080fd5b5061060a6004803603810190610605919061392d565b611c60565b005b34801561061857600080fd5b50610621611ce7565b60405161062e9190613ae3565b60405180910390f35b34801561064357600080fd5b5061064c611cfd565b6040516106599190613a4d565b60405180910390f35b34801561066e57600080fd5b50610677611d27565b60405161068491906139ea565b60405180910390f35b34801561069957600080fd5b506106b460048036038101906106af9190613f53565b611db5565b005b3480156106c257600080fd5b506106cb611f28565b6040516106d89190613ae3565b60405180910390f35b3480156106ed57600080fd5b5061070860048036038101906107039190614034565b611f2e565b005b610724600480360381019061071f91906140b7565b612113565b005b34801561073257600080fd5b5061074d6004803603810190610748919061392d565b612269565b005b34801561075b57600080fd5b506107766004803603810190610771919061392d565b6122f0565b60405161078391906139ea565b60405180910390f35b34801561079857600080fd5b506107b360048036038101906107ae919061392d565b612395565b005b3480156107c157600080fd5b506107ca61241c565b6040516107d79190613ae3565b60405180910390f35b3480156107ec57600080fd5b506107f5612422565b6040516108029190613ae3565b60405180910390f35b34801561081757600080fd5b50610832600480360381019061082d91906140f7565b612428565b60405161083f91906138dc565b60405180910390f35b610862600480360381019061085d919061392d565b61243c565b005b34801561087057600080fd5b5061088b60048036038101906108869190613d18565b6126c0565b005b34801561089957600080fd5b506108b460048036038101906108af9190613a94565b612803565b005b3480156108c257600080fd5b506108dd60048036038101906108d89190614137565b6129c3565b005b3480156108eb57600080fd5b506108f4612a4a565b6040516109019190613ae3565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109d557507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a3d57507f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610aa557507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16610ad0611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614610b2857806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401610b1f9190613a4d565b60405180910390fd5b81600b819055505050565b60018054610b4090614193565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6c90614193565b8015610bb95780601f10610b8e57610100808354040283529160200191610bb9565b820191906000526020600020905b815481529060010190602001808311610b9c57829003601f168201915b505050505081565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b80610bfe81612a50565b610c3f57806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401610c369190613ae3565b60405180910390fd5b60003390506000610c4f84612a6f565b90508073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610cc157846040517ff2b21e1c000000000000000000000000000000000000000000000000000000008152600401610cb89190613a4d565b60405180910390fd5b6000610cce828487612b35565b905080610d16578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401610d0d939291906141c4565b60405180910390fd5b856003600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b6000610dd5612bee565b905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610faa573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e4c57610e47848484612bfd565b610fb6565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610e959291906141fb565b602060405180830381865afa158015610eb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed69190614239565b8015610f6857506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610f269291906141fb565b602060405180830381865afa158015610f43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f679190614239565b5b610fa957336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610fa09190613a4d565b60405180910390fd5b5b610fb5848484612bfd565b5b50505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161461102a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611021906142b2565b60405180910390fd5b600280600381111561103f5761103e613e95565b5b601060009054906101000a900460ff16600381111561106157611060613e95565b5b146110a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110989061431e565b60405180910390fd5b6000801b600d54036110df576040517f93dff14200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000339050600f60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561117357806040517f6acdb09500000000000000000000000000000000000000000000000000000000815260040161116a9190613a4d565b60405180910390fd5b6000816040516020016111869190614386565b6040516020818303038152906040528051906020012090506000600d546111ad8684612d9d565b149050806111f257826040517f186a628d0000000000000000000000000000000000000000000000000000000081526004016111e99190613a4d565b60405180910390fd5b60006111fc610dcb565b9050600c54600a548261120f91906143d0565b1115611250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124790614450565b60405180910390fd5b6008543414611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b906144bc565b60405180910390fd5b6112a033600a54612df3565b6001600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050565b600061130b83612fae565b82106113505782826040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526004016113479291906144dc565b60405180910390fd5b600080600190505b6000548110156113e25761136b81612a50565b80156113aa575061137b81612a6f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b156113cf578184036113c05780925050506113e5565b81806113cb90614505565b9250505b80806113da90614505565b915050611358565b50505b92915050565b60116020528060005260406000206000915090505481565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156115d3573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114755761147084848461310b565b6115df565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016114be9291906141fb565b602060405180830381865afa1580156114db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ff9190614239565b801561159157506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161154f9291906141fb565b602060405180830381865afa15801561156c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115909190614239565b5b6115d257336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016115c99190613a4d565b60405180910390fd5b5b6115de84848461310b565b5b50505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611653576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164a906142b2565b60405180910390fd5b600180600381111561166857611667613e95565b5b601060009054906101000a900460ff16600381111561168a57611689613e95565b5b146116ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c19061431e565b60405180910390fd5b6000801b600d5403611708576040517f93dff14200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000339050600e60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561179c57806040517f6acdb0950000000000000000000000000000000000000000000000000000000081526004016117939190613a4d565b60405180910390fd5b6000816040516020016117af9190614386565b6040516020818303038152906040528051906020012090506000600d546117d68684612d9d565b1490508061181b57826040517f186a628d0000000000000000000000000000000000000000000000000000000081526004016118129190613a4d565b60405180910390fd5b6000611825610dcb565b9050600c54600a548261183891906143d0565b1115611879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187090614450565b60405180910390fd5b60085434146118bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b4906144bc565b60405180910390fd5b6118c933600a54612df3565b6001600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050565b6000611933611ce7565b821061197657816040517f125c19b000000000000000000000000000000000000000000000000000000000815260040161196d9190613ae3565b60405180910390fd5b60018261198391906143d0565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166119ae611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611a0657806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016119fd9190613a4d565b60405180910390fd5b611a0f8261312b565b5050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611a37611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611a8f57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611a869190613a4d565b60405180910390fd5b81601060006101000a81548160ff02191690836003811115611ab457611ab3613e95565b5b02179055505050565b601060009054906101000a900460ff1681565b600081611adc81612a50565b611b1d57806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401611b149190613ae3565b60405180910390fd5b611b2683612a6f565b915050919050565b600a5481565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611b58611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611bb057806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611ba79190613a4d565b60405180910390fd5b6000611bba610dcb565b9050808311611bfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf5906145bf565b60405180910390fd5b600c548310611c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3990614651565b60405180910390fd5b82600c81905550505050565b6000611c5982612fae565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611c84611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611cdc57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611cd39190613a4d565b60405180910390fd5b816008819055505050565b60006001600054611cf89190614671565b905090565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60028054611d3490614193565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6090614193565b8015611dad5780601f10611d8257610100808354040283529160200191611dad565b820191906000526020600020905b815481529060010190602001808311611d9057829003601f168201915b505050505081565b60003390508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e2a57826040517ff2b21e1c000000000000000000000000000000000000000000000000000000008152600401611e219190613a4d565b60405180910390fd5b81600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611f1b91906138dc565b60405180910390a3505050565b60095481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156120ff573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611fa157611f9c8585858561313e565b61210c565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611fea9291906141fb565b602060405180830381865afa158015612007573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202b9190614239565b80156120bd57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161207b9291906141fb565b602060405180830381865afa158015612098573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bc9190614239565b5b6120fe57336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016120f59190613a4d565b60405180910390fd5b5b61210b8585858561313e565b5b5050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16612137611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461218f57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016121869190613a4d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146121fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121f4906142b2565b60405180910390fd5b6000612207610dcb565b9050600c54848261221891906143d0565b1115612259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225090614450565b60405180910390fd5b6122638385612df3565b50505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661228d611cfd565b73ffffffffffffffffffffffffffffffffffffffff16146122e557806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016122dc9190613a4d565b60405180910390fd5b816009819055505050565b6060816122fc81612a50565b61233d57806040517f1cf4d9a40000000000000000000000000000000000000000000000000000000081526004016123349190613ae3565b60405180910390fd5b60006006805461234c90614193565b9050116123615761235c8361319c565b61238d565b600661236c8461319c565b60405160200161237d929190614779565b6040516020818303038152906040525b915050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166123b9611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461241157806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016124089190613a4d565b60405180910390fd5b81600a819055505050565b600b5481565b600c5481565b600061243483836132fc565b905092915050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146124aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124a1906142b2565b60405180910390fd5b60038060038111156124bf576124be613e95565b5b601060009054906101000a900460ff1660038111156124e1576124e0613e95565b5b14612521576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125189061431e565b60405180910390fd5b600061252b610dcb565b9050600b5483601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461257b91906143d0565b11156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b3906147e9565b60405180910390fd5b600c5483826125cb91906143d0565b111561260c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161260390614450565b60405180910390fd5b6009548361261a9190614809565b341461265b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612652906144bc565b60405180910390fd5b6126653384612df3565b82601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546126b491906143d0565b92505081905550505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166126e4611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461273c57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016127339190613a4d565b60405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16612827611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461287f57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016128769190613a4d565b60405180910390fd5b6000479050600081116128c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128be90614897565b60405180910390fd5b8083111561290a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290190614903565b60405180910390fd5b600084905060008173ffffffffffffffffffffffffffffffffffffffff168560405161293590614954565b60006040518083038185875af1925050503d8060008114612972576040519150601f19603f3d011682016040523d82523d6000602084013e612977565b606091505b50509050806129bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b2906149b5565b60405180910390fd5b505050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166129e7611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614612a3f57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401612a369190613a4d565b60405180910390fd5b81600d819055505050565b60085481565b6000808203612a625760009050612a6a565b600054821090505b919050565b60008082905060006005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b2b578180612aed906149d5565b9250506005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050612aae565b8092505050919050565b6000808473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bd057506003600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80612be15750612be085856132fc565b5b9050809150509392505050565b6000612bf8611ce7565b905090565b80612c0781612a50565b612c4857806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401612c3f9190613ae3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612cae576040517f14242cb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390506000612cbe84612a6f565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612d34578086856040517fe02b28e7000000000000000000000000000000000000000000000000000000008152600401612d2b939291906141c4565b60405180910390fd5b6000612d41828487612b35565b905080612d89578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401612d80939291906141c4565b60405180910390fd5b612d94828787613390565b50505050505050565b60008082905060005b8451811015612de857612dd382868381518110612dc657612dc56149fe565b5b6020026020010151613678565b91508080612de090614505565b915050612da6565b508091505092915050565b60008054905060008282612e0791906143d0565b90506000600182612e189190614671565b9050846005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082811115612ec757846005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b81600081905550612eea60008685604051806020016040528060008152506136a3565b612f2b57846040517f015be56a000000000000000000000000000000000000000000000000000000008152600401612f229190613a4d565b60405180910390fd5b60008390505b82811015612fa657808673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480612f9f90614505565b9050612f31565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fec5760009050613106565b60008080600190505b6000548110156130ff5761300881612a50565b156130ee57600073ffffffffffffffffffffffffffffffffffffffff166005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146130ab576005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b8173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036130ed5782806130e990614505565b9350505b5b806130f890614505565b9050612ff5565b5081925050505b919050565b61312683838360405180602001604052806000815250611f2e565b505050565b806006908161313a9190614bc4565b5050565b613149848484610dda565b613155848484846136a3565b61319657826040517f015be56a00000000000000000000000000000000000000000000000000000000815260040161318d9190613a4d565b60405180910390fd5b50505050565b6060600082036131e3576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506132f7565b600082905060005b600082146132155780806131fe90614505565b915050600a8261320e9190614cc5565b91506131eb565b60008167ffffffffffffffff81111561323157613230613b56565b5b6040519080825280601f01601f1916602001820160405280156132635781602001600182028036833780820191505090505b5090505b600085146132f05760018261327c9190614671565b9150600a8561328b9190614cf6565b603061329791906143d0565b60f81b8183815181106132ad576132ac6149fe565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a856132e99190614cc5565b9450613267565b8093505050505b919050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60006003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600182116133f4576001613402565b6001826134019190614671565b5b9050600060018361341391906143d0565b90506000838310801561342b575061342a83612a50565b5b80156134965750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b905060006134a383612a50565b801561350e5750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050811561356957866005600086815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80156135c257866005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b856005600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a450505050505050565b60008183106136905761368b8284613811565b61369b565b61369a8383613811565b5b905092915050565b600080843b90506000811115613803578473ffffffffffffffffffffffffffffffffffffffff1663150b7a02338887876040518563ffffffff1660e01b81526004016136f29493929190614d7c565b6020604051808303816000875af192505050801561372e57506040513d601f19601f8201168201806040525081019061372b9190614ddd565b60015b6137b2573d806000811461375e576040519150601f19603f3d011682016040523d82523d6000602084013e613763565b606091505b5060008151036137aa57856040517f015be56a0000000000000000000000000000000000000000000000000000000081526004016137a19190613a4d565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161492505050613809565b60019150505b949350505050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6138718161383c565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9613832565b5b60006138b88482850161387f565b91505092915050565b60008115159050919050565b6138d6816138c1565b82525050565b60006020820190506138f160008301846138cd565b92915050565b6000819050919050565b61390a816138f7565b811461391557600080fd5b50565b60008135905061392781613901565b92915050565b60006020828403121561394357613942613832565b5b600061395184828501613918565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613994578082015181840152602081019050613979565b60008484015250505050565b6000601f19601f8301169050919050565b60006139bc8261395a565b6139c68185613965565b93506139d6818560208601613976565b6139df816139a0565b840191505092915050565b60006020820190508181036000830152613a0481846139b1565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a3782613a0c565b9050919050565b613a4781613a2c565b82525050565b6000602082019050613a626000830184613a3e565b92915050565b613a7181613a2c565b8114613a7c57600080fd5b50565b600081359050613a8e81613a68565b92915050565b60008060408385031215613aab57613aaa613832565b5b6000613ab985828601613a7f565b9250506020613aca85828601613918565b9150509250929050565b613add816138f7565b82525050565b6000602082019050613af86000830184613ad4565b92915050565b600080600060608486031215613b1757613b16613832565b5b6000613b2586828701613a7f565b9350506020613b3686828701613a7f565b9250506040613b4786828701613918565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b8e826139a0565b810181811067ffffffffffffffff82111715613bad57613bac613b56565b5b80604052505050565b6000613bc0613828565b9050613bcc8282613b85565b919050565b600067ffffffffffffffff821115613bec57613beb613b56565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b613c1581613c02565b8114613c2057600080fd5b50565b600081359050613c3281613c0c565b92915050565b6000613c4b613c4684613bd1565b613bb6565b90508083825260208201905060208402830185811115613c6e57613c6d613bfd565b5b835b81811015613c975780613c838882613c23565b845260208401935050602081019050613c70565b5050509392505050565b600082601f830112613cb657613cb5613b51565b5b8135613cc6848260208601613c38565b91505092915050565b600060208284031215613ce557613ce4613832565b5b600082013567ffffffffffffffff811115613d0357613d02613837565b5b613d0f84828501613ca1565b91505092915050565b600060208284031215613d2e57613d2d613832565b5b6000613d3c84828501613a7f565b91505092915050565b600080fd5b600067ffffffffffffffff821115613d6557613d64613b56565b5b613d6e826139a0565b9050602081019050919050565b82818337600083830152505050565b6000613d9d613d9884613d4a565b613bb6565b905082815260208101848484011115613db957613db8613d45565b5b613dc4848285613d7b565b509392505050565b600082601f830112613de157613de0613b51565b5b8135613df1848260208601613d8a565b91505092915050565b600060208284031215613e1057613e0f613832565b5b600082013567ffffffffffffffff811115613e2e57613e2d613837565b5b613e3a84828501613dcc565b91505092915050565b60048110613e5057600080fd5b50565b600081359050613e6281613e43565b92915050565b600060208284031215613e7e57613e7d613832565b5b6000613e8c84828501613e53565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110613ed557613ed4613e95565b5b50565b6000819050613ee682613ec4565b919050565b6000613ef682613ed8565b9050919050565b613f0681613eeb565b82525050565b6000602082019050613f216000830184613efd565b92915050565b613f30816138c1565b8114613f3b57600080fd5b50565b600081359050613f4d81613f27565b92915050565b60008060408385031215613f6a57613f69613832565b5b6000613f7885828601613a7f565b9250506020613f8985828601613f3e565b9150509250929050565b600067ffffffffffffffff821115613fae57613fad613b56565b5b613fb7826139a0565b9050602081019050919050565b6000613fd7613fd284613f93565b613bb6565b905082815260208101848484011115613ff357613ff2613d45565b5b613ffe848285613d7b565b509392505050565b600082601f83011261401b5761401a613b51565b5b813561402b848260208601613fc4565b91505092915050565b6000806000806080858703121561404e5761404d613832565b5b600061405c87828801613a7f565b945050602061406d87828801613a7f565b935050604061407e87828801613918565b925050606085013567ffffffffffffffff81111561409f5761409e613837565b5b6140ab87828801614006565b91505092959194509250565b600080604083850312156140ce576140cd613832565b5b60006140dc85828601613918565b92505060206140ed85828601613a7f565b9150509250929050565b6000806040838503121561410e5761410d613832565b5b600061411c85828601613a7f565b925050602061412d85828601613a7f565b9150509250929050565b60006020828403121561414d5761414c613832565b5b600061415b84828501613c23565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806141ab57607f821691505b6020821081036141be576141bd614164565b5b50919050565b60006060820190506141d96000830186613a3e565b6141e66020830185613a3e565b6141f36040830184613ad4565b949350505050565b60006040820190506142106000830185613a3e565b61421d6020830184613a3e565b9392505050565b60008151905061423381613f27565b92915050565b60006020828403121561424f5761424e613832565b5b600061425d84828501614224565b91505092915050565b7f4e6f20736d61727420636f6e7472616374732061726520616c6c6f7765640000600082015250565b600061429c601e83613965565b91506142a782614266565b602082019050919050565b600060208201905081810360008301526142cb8161428f565b9050919050565b7f53616c65206e6f74206163746976650000000000000000000000000000000000600082015250565b6000614308600f83613965565b9150614313826142d2565b602082019050919050565b60006020820190508181036000830152614337816142fb565b9050919050565b60008160601b9050919050565b60006143568261433e565b9050919050565b60006143688261434b565b9050919050565b61438061437b82613a2c565b61435d565b82525050565b6000614392828461436f565b60148201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006143db826138f7565b91506143e6836138f7565b92508282019050808211156143fe576143fd6143a1565b5b92915050565b7f4578636565647320737570706c79000000000000000000000000000000000000600082015250565b600061443a600e83613965565b915061444582614404565b602082019050919050565b600060208201905081810360008301526144698161442d565b9050919050565b7f45746865722073656e74206973206e6f7420636f727265637400000000000000600082015250565b60006144a6601983613965565b91506144b182614470565b602082019050919050565b600060208201905081810360008301526144d581614499565b9050919050565b60006040820190506144f16000830185613a3e565b6144fe6020830184613ad4565b9392505050565b6000614510826138f7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614542576145416143a1565b5b600182019050919050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2063757272656e7420737570706c7900000000000000000000000000000000602082015250565b60006145a9603083613965565b91506145b48261454d565b604082019050919050565b600060208201905081810360008301526145d88161459c565b9050919050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2070726576696f7573206d617820737570706c790000000000000000000000602082015250565b600061463b603583613965565b9150614646826145df565b604082019050919050565b6000602082019050818103600083015261466a8161462e565b9050919050565b600061467c826138f7565b9150614687836138f7565b925082820390508181111561469f5761469e6143a1565b5b92915050565b600081905092915050565b60008190508160005260206000209050919050565b600081546146d281614193565b6146dc81866146a5565b945060018216600081146146f7576001811461470c5761473f565b60ff198316865281151582028601935061473f565b614715856146b0565b60005b8381101561473757815481890152600182019150602081019050614718565b838801955050505b50505092915050565b60006147538261395a565b61475d81856146a5565b935061476d818560208601613976565b80840191505092915050565b600061478582856146c5565b91506147918284614748565b91508190509392505050565b7f45786365656473206d696e74207065722077616c6c6574000000000000000000600082015250565b60006147d3601783613965565b91506147de8261479d565b602082019050919050565b60006020820190508181036000830152614802816147c6565b9050919050565b6000614814826138f7565b915061481f836138f7565b925082820261482d816138f7565b91508282048414831517614844576148436143a1565b5b5092915050565b7f4e6f2062616c616e636520746f20776974686472617700000000000000000000600082015250565b6000614881601683613965565b915061488c8261484b565b602082019050919050565b600060208201905081810360008301526148b081614874565b9050919050565b7f416d6f756e74206973206e6f742076616c696400000000000000000000000000600082015250565b60006148ed601383613965565b91506148f8826148b7565b602082019050919050565b6000602082019050818103600083015261491c816148e0565b9050919050565b600081905092915050565b50565b600061493e600083614923565b91506149498261492e565b600082019050919050565b600061495f82614931565b9150819050919050565b7f5472616e73616374696f6e206661696c65640000000000000000000000000000600082015250565b600061499f601283613965565b91506149aa82614969565b602082019050919050565b600060208201905081810360008301526149ce81614992565b9050919050565b60006149e0826138f7565b9150600082036149f3576149f26143a1565b5b600182039050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020601f8301049050919050565b600082821b905092915050565b600060088302614a7a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614a3d565b614a848683614a3d565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614ac1614abc614ab7846138f7565b614a9c565b6138f7565b9050919050565b6000819050919050565b614adb83614aa6565b614aef614ae782614ac8565b848454614a4a565b825550505050565b600090565b614b04614af7565b614b0f818484614ad2565b505050565b5b81811015614b3357614b28600082614afc565b600181019050614b15565b5050565b601f821115614b7857614b49816146b0565b614b5284614a2d565b81016020851015614b61578190505b614b75614b6d85614a2d565b830182614b14565b50505b505050565b600082821c905092915050565b6000614b9b60001984600802614b7d565b1980831691505092915050565b6000614bb48383614b8a565b9150826002028217905092915050565b614bcd8261395a565b67ffffffffffffffff811115614be657614be5613b56565b5b614bf08254614193565b614bfb828285614b37565b600060209050601f831160018114614c2e5760008415614c1c578287015190505b614c268582614ba8565b865550614c8e565b601f198416614c3c866146b0565b60005b82811015614c6457848901518255600182019150602085019450602081019050614c3f565b86831015614c815784890151614c7d601f891682614b8a565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614cd0826138f7565b9150614cdb836138f7565b925082614ceb57614cea614c96565b5b828204905092915050565b6000614d01826138f7565b9150614d0c836138f7565b925082614d1c57614d1b614c96565b5b828206905092915050565b600081519050919050565b600082825260208201905092915050565b6000614d4e82614d27565b614d588185614d32565b9350614d68818560208601613976565b614d71816139a0565b840191505092915050565b6000608082019050614d916000830187613a3e565b614d9e6020830186613a3e565b614dab6040830185613ad4565b8181036060830152614dbd8184614d43565b905095945050505050565b600081519050614dd781613868565b92915050565b600060208284031215614df357614df2613832565b5b6000614e0184828501614dc8565b9150509291505056fea2646970667358221220ff14bd865b00fa40770dcc60e989ad61973c8b2b0c621a86db37e1f3ba25422964736f6c63430008110033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000a556e646561644368656600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b554e4445414443484546530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040697066733a2f2f516d614c484d7162626438594e5934787a4b7458596843506654764b5755794d4d6f72566155347838456f69746e2f70726572657665616c2f

Deployed Bytecode

0x6080604052600436106102305760003560e01c806370a082311161012e578063c87b56dd116100ab578063efd0cbf91161006f578063efd0cbf914610848578063f2fde38b14610864578063f3fef3a31461088d578063f5aa406d146108b6578063fc1a1c36146108df57610230565b8063c87b56dd1461074f578063c95d83c61461078c578063cfe1908d146107b5578063d5abeb01146107e0578063e985e9c51461080b57610230565b8063a22cb465116100f2578063a22cb4651461068d578063a945bf80146106b6578063b88d4fde146106e1578063bc63f02e1461070a578063c62752551461072657610230565b806370a08231146105a6578063717d57d3146105e35780637e9845f51461060c5780638da5cb5b1461063757806395d89b411461066257610230565b80633a602b4d116101bc5780635a67de07116101805780635a67de07146104c1578063603f4d52146104ea5780636352211e1461051557806366cc5f0d146105525780636f8b44b01461057d57610230565b80633a602b4d146103d957806342842e0e1461041657806344d843811461043f5780634f6ccce71461045b57806355f804b31461049857610230565b8063095ea7b311610203578063095ea7b31461030357806318160ddd1461032c57806323b872dd1461035757806328bb1a2e146103805780632f745c591461039c57610230565b806301ffc9a71461023557806302c366bc1461027257806306fdde031461029b578063081812fc146102c6575b600080fd5b34801561024157600080fd5b5061025c60048036038101906102579190613894565b61090a565b60405161026991906138dc565b60405180910390f35b34801561027e57600080fd5b506102996004803603810190610294919061392d565b610aac565b005b3480156102a757600080fd5b506102b0610b33565b6040516102bd91906139ea565b60405180910390f35b3480156102d257600080fd5b506102ed60048036038101906102e8919061392d565b610bc1565b6040516102fa9190613a4d565b60405180910390f35b34801561030f57600080fd5b5061032a60048036038101906103259190613a94565b610bf4565b005b34801561033857600080fd5b50610341610dcb565b60405161034e9190613ae3565b60405180910390f35b34801561036357600080fd5b5061037e60048036038101906103799190613afe565b610dda565b005b61039a60048036038101906103959190613ccf565b610fbc565b005b3480156103a857600080fd5b506103c360048036038101906103be9190613a94565b611300565b6040516103d09190613ae3565b60405180910390f35b3480156103e557600080fd5b5061040060048036038101906103fb9190613d18565b6113eb565b60405161040d9190613ae3565b60405180910390f35b34801561042257600080fd5b5061043d60048036038101906104389190613afe565b611403565b005b61045960048036038101906104549190613ccf565b6115e5565b005b34801561046757600080fd5b50610482600480360381019061047d919061392d565b611929565b60405161048f9190613ae3565b60405180910390f35b3480156104a457600080fd5b506104bf60048036038101906104ba9190613dfa565b61198a565b005b3480156104cd57600080fd5b506104e860048036038101906104e39190613e68565b611a13565b005b3480156104f657600080fd5b506104ff611abd565b60405161050c9190613f0c565b60405180910390f35b34801561052157600080fd5b5061053c6004803603810190610537919061392d565b611ad0565b6040516105499190613a4d565b60405180910390f35b34801561055e57600080fd5b50610567611b2e565b6040516105749190613ae3565b60405180910390f35b34801561058957600080fd5b506105a4600480360381019061059f919061392d565b611b34565b005b3480156105b257600080fd5b506105cd60048036038101906105c89190613d18565b611c4e565b6040516105da9190613ae3565b60405180910390f35b3480156105ef57600080fd5b5061060a6004803603810190610605919061392d565b611c60565b005b34801561061857600080fd5b50610621611ce7565b60405161062e9190613ae3565b60405180910390f35b34801561064357600080fd5b5061064c611cfd565b6040516106599190613a4d565b60405180910390f35b34801561066e57600080fd5b50610677611d27565b60405161068491906139ea565b60405180910390f35b34801561069957600080fd5b506106b460048036038101906106af9190613f53565b611db5565b005b3480156106c257600080fd5b506106cb611f28565b6040516106d89190613ae3565b60405180910390f35b3480156106ed57600080fd5b5061070860048036038101906107039190614034565b611f2e565b005b610724600480360381019061071f91906140b7565b612113565b005b34801561073257600080fd5b5061074d6004803603810190610748919061392d565b612269565b005b34801561075b57600080fd5b506107766004803603810190610771919061392d565b6122f0565b60405161078391906139ea565b60405180910390f35b34801561079857600080fd5b506107b360048036038101906107ae919061392d565b612395565b005b3480156107c157600080fd5b506107ca61241c565b6040516107d79190613ae3565b60405180910390f35b3480156107ec57600080fd5b506107f5612422565b6040516108029190613ae3565b60405180910390f35b34801561081757600080fd5b50610832600480360381019061082d91906140f7565b612428565b60405161083f91906138dc565b60405180910390f35b610862600480360381019061085d919061392d565b61243c565b005b34801561087057600080fd5b5061088b60048036038101906108869190613d18565b6126c0565b005b34801561089957600080fd5b506108b460048036038101906108af9190613a94565b612803565b005b3480156108c257600080fd5b506108dd60048036038101906108d89190614137565b6129c3565b005b3480156108eb57600080fd5b506108f4612a4a565b6040516109019190613ae3565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109d557507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a3d57507f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610aa557507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16610ad0611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614610b2857806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401610b1f9190613a4d565b60405180910390fd5b81600b819055505050565b60018054610b4090614193565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6c90614193565b8015610bb95780601f10610b8e57610100808354040283529160200191610bb9565b820191906000526020600020905b815481529060010190602001808311610b9c57829003601f168201915b505050505081565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b80610bfe81612a50565b610c3f57806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401610c369190613ae3565b60405180910390fd5b60003390506000610c4f84612a6f565b90508073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610cc157846040517ff2b21e1c000000000000000000000000000000000000000000000000000000008152600401610cb89190613a4d565b60405180910390fd5b6000610cce828487612b35565b905080610d16578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401610d0d939291906141c4565b60405180910390fd5b856003600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b6000610dd5612bee565b905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610faa573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e4c57610e47848484612bfd565b610fb6565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610e959291906141fb565b602060405180830381865afa158015610eb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed69190614239565b8015610f6857506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610f269291906141fb565b602060405180830381865afa158015610f43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f679190614239565b5b610fa957336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610fa09190613a4d565b60405180910390fd5b5b610fb5848484612bfd565b5b50505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161461102a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611021906142b2565b60405180910390fd5b600280600381111561103f5761103e613e95565b5b601060009054906101000a900460ff16600381111561106157611060613e95565b5b146110a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110989061431e565b60405180910390fd5b6000801b600d54036110df576040517f93dff14200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000339050600f60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561117357806040517f6acdb09500000000000000000000000000000000000000000000000000000000815260040161116a9190613a4d565b60405180910390fd5b6000816040516020016111869190614386565b6040516020818303038152906040528051906020012090506000600d546111ad8684612d9d565b149050806111f257826040517f186a628d0000000000000000000000000000000000000000000000000000000081526004016111e99190613a4d565b60405180910390fd5b60006111fc610dcb565b9050600c54600a548261120f91906143d0565b1115611250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124790614450565b60405180910390fd5b6008543414611294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128b906144bc565b60405180910390fd5b6112a033600a54612df3565b6001600f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050565b600061130b83612fae565b82106113505782826040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526004016113479291906144dc565b60405180910390fd5b600080600190505b6000548110156113e25761136b81612a50565b80156113aa575061137b81612a6f565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b156113cf578184036113c05780925050506113e5565b81806113cb90614505565b9250505b80806113da90614505565b915050611358565b50505b92915050565b60116020528060005260406000206000915090505481565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156115d3573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036114755761147084848461310b565b6115df565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016114be9291906141fb565b602060405180830381865afa1580156114db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ff9190614239565b801561159157506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161154f9291906141fb565b602060405180830381865afa15801561156c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115909190614239565b5b6115d257336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016115c99190613a4d565b60405180910390fd5b5b6115de84848461310b565b5b50505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611653576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164a906142b2565b60405180910390fd5b600180600381111561166857611667613e95565b5b601060009054906101000a900460ff16600381111561168a57611689613e95565b5b146116ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c19061431e565b60405180910390fd5b6000801b600d5403611708576040517f93dff14200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000339050600e60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561179c57806040517f6acdb0950000000000000000000000000000000000000000000000000000000081526004016117939190613a4d565b60405180910390fd5b6000816040516020016117af9190614386565b6040516020818303038152906040528051906020012090506000600d546117d68684612d9d565b1490508061181b57826040517f186a628d0000000000000000000000000000000000000000000000000000000081526004016118129190613a4d565b60405180910390fd5b6000611825610dcb565b9050600c54600a548261183891906143d0565b1115611879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161187090614450565b60405180910390fd5b60085434146118bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b4906144bc565b60405180910390fd5b6118c933600a54612df3565b6001600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050565b6000611933611ce7565b821061197657816040517f125c19b000000000000000000000000000000000000000000000000000000000815260040161196d9190613ae3565b60405180910390fd5b60018261198391906143d0565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166119ae611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611a0657806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016119fd9190613a4d565b60405180910390fd5b611a0f8261312b565b5050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611a37611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611a8f57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611a869190613a4d565b60405180910390fd5b81601060006101000a81548160ff02191690836003811115611ab457611ab3613e95565b5b02179055505050565b601060009054906101000a900460ff1681565b600081611adc81612a50565b611b1d57806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401611b149190613ae3565b60405180910390fd5b611b2683612a6f565b915050919050565b600a5481565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611b58611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611bb057806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611ba79190613a4d565b60405180910390fd5b6000611bba610dcb565b9050808311611bfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf5906145bf565b60405180910390fd5b600c548310611c42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3990614651565b60405180910390fd5b82600c81905550505050565b6000611c5982612fae565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611c84611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614611cdc57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611cd39190613a4d565b60405180910390fd5b816008819055505050565b60006001600054611cf89190614671565b905090565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60028054611d3490614193565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6090614193565b8015611dad5780601f10611d8257610100808354040283529160200191611dad565b820191906000526020600020905b815481529060010190602001808311611d9057829003601f168201915b505050505081565b60003390508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611e2a57826040517ff2b21e1c000000000000000000000000000000000000000000000000000000008152600401611e219190613a4d565b60405180910390fd5b81600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611f1b91906138dc565b60405180910390a3505050565b60095481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156120ff573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611fa157611f9c8585858561313e565b61210c565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611fea9291906141fb565b602060405180830381865afa158015612007573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202b9190614239565b80156120bd57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161207b9291906141fb565b602060405180830381865afa158015612098573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bc9190614239565b5b6120fe57336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016120f59190613a4d565b60405180910390fd5b5b61210b8585858561313e565b5b5050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16612137611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461218f57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016121869190613a4d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146121fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121f4906142b2565b60405180910390fd5b6000612207610dcb565b9050600c54848261221891906143d0565b1115612259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225090614450565b60405180910390fd5b6122638385612df3565b50505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661228d611cfd565b73ffffffffffffffffffffffffffffffffffffffff16146122e557806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016122dc9190613a4d565b60405180910390fd5b816009819055505050565b6060816122fc81612a50565b61233d57806040517f1cf4d9a40000000000000000000000000000000000000000000000000000000081526004016123349190613ae3565b60405180910390fd5b60006006805461234c90614193565b9050116123615761235c8361319c565b61238d565b600661236c8461319c565b60405160200161237d929190614779565b6040516020818303038152906040525b915050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166123b9611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461241157806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016124089190613a4d565b60405180910390fd5b81600a819055505050565b600b5481565b600c5481565b600061243483836132fc565b905092915050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146124aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124a1906142b2565b60405180910390fd5b60038060038111156124bf576124be613e95565b5b601060009054906101000a900460ff1660038111156124e1576124e0613e95565b5b14612521576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125189061431e565b60405180910390fd5b600061252b610dcb565b9050600b5483601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461257b91906143d0565b11156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b3906147e9565b60405180910390fd5b600c5483826125cb91906143d0565b111561260c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161260390614450565b60405180910390fd5b6009548361261a9190614809565b341461265b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612652906144bc565b60405180910390fd5b6126653384612df3565b82601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546126b491906143d0565b92505081905550505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166126e4611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461273c57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016127339190613a4d565b60405180910390fd5b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16612827611cfd565b73ffffffffffffffffffffffffffffffffffffffff161461287f57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016128769190613a4d565b60405180910390fd5b6000479050600081116128c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128be90614897565b60405180910390fd5b8083111561290a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290190614903565b60405180910390fd5b600084905060008173ffffffffffffffffffffffffffffffffffffffff168560405161293590614954565b60006040518083038185875af1925050503d8060008114612972576040519150601f19603f3d011682016040523d82523d6000602084013e612977565b606091505b50509050806129bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b2906149b5565b60405180910390fd5b505050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166129e7611cfd565b73ffffffffffffffffffffffffffffffffffffffff1614612a3f57806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401612a369190613a4d565b60405180910390fd5b81600d819055505050565b60085481565b6000808203612a625760009050612a6a565b600054821090505b919050565b60008082905060006005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612b2b578180612aed906149d5565b9250506005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050612aae565b8092505050919050565b6000808473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612bd057506003600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80612be15750612be085856132fc565b5b9050809150509392505050565b6000612bf8611ce7565b905090565b80612c0781612a50565b612c4857806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401612c3f9190613ae3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612cae576040517f14242cb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390506000612cbe84612a6f565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612d34578086856040517fe02b28e7000000000000000000000000000000000000000000000000000000008152600401612d2b939291906141c4565b60405180910390fd5b6000612d41828487612b35565b905080612d89578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401612d80939291906141c4565b60405180910390fd5b612d94828787613390565b50505050505050565b60008082905060005b8451811015612de857612dd382868381518110612dc657612dc56149fe565b5b6020026020010151613678565b91508080612de090614505565b915050612da6565b508091505092915050565b60008054905060008282612e0791906143d0565b90506000600182612e189190614671565b9050846005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082811115612ec757846005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b81600081905550612eea60008685604051806020016040528060008152506136a3565b612f2b57846040517f015be56a000000000000000000000000000000000000000000000000000000008152600401612f229190613a4d565b60405180910390fd5b60008390505b82811015612fa657808673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480612f9f90614505565b9050612f31565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612fec5760009050613106565b60008080600190505b6000548110156130ff5761300881612a50565b156130ee57600073ffffffffffffffffffffffffffffffffffffffff166005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146130ab576005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b8173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036130ed5782806130e990614505565b9350505b5b806130f890614505565b9050612ff5565b5081925050505b919050565b61312683838360405180602001604052806000815250611f2e565b505050565b806006908161313a9190614bc4565b5050565b613149848484610dda565b613155848484846136a3565b61319657826040517f015be56a00000000000000000000000000000000000000000000000000000000815260040161318d9190613a4d565b60405180910390fd5b50505050565b6060600082036131e3576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506132f7565b600082905060005b600082146132155780806131fe90614505565b915050600a8261320e9190614cc5565b91506131eb565b60008167ffffffffffffffff81111561323157613230613b56565b5b6040519080825280601f01601f1916602001820160405280156132635781602001600182028036833780820191505090505b5090505b600085146132f05760018261327c9190614671565b9150600a8561328b9190614cf6565b603061329791906143d0565b60f81b8183815181106132ad576132ac6149fe565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a856132e99190614cc5565b9450613267565b8093505050505b919050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60006003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600182116133f4576001613402565b6001826134019190614671565b5b9050600060018361341391906143d0565b90506000838310801561342b575061342a83612a50565b5b80156134965750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b905060006134a383612a50565b801561350e5750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050811561356957866005600086815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b80156135c257866005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b856005600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a450505050505050565b60008183106136905761368b8284613811565b61369b565b61369a8383613811565b5b905092915050565b600080843b90506000811115613803578473ffffffffffffffffffffffffffffffffffffffff1663150b7a02338887876040518563ffffffff1660e01b81526004016136f29493929190614d7c565b6020604051808303816000875af192505050801561372e57506040513d601f19601f8201168201806040525081019061372b9190614ddd565b60015b6137b2573d806000811461375e576040519150601f19603f3d011682016040523d82523d6000602084013e613763565b606091505b5060008151036137aa57856040517f015be56a0000000000000000000000000000000000000000000000000000000081526004016137a19190613a4d565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161492505050613809565b60019150505b949350505050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6138718161383c565b811461387c57600080fd5b50565b60008135905061388e81613868565b92915050565b6000602082840312156138aa576138a9613832565b5b60006138b88482850161387f565b91505092915050565b60008115159050919050565b6138d6816138c1565b82525050565b60006020820190506138f160008301846138cd565b92915050565b6000819050919050565b61390a816138f7565b811461391557600080fd5b50565b60008135905061392781613901565b92915050565b60006020828403121561394357613942613832565b5b600061395184828501613918565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613994578082015181840152602081019050613979565b60008484015250505050565b6000601f19601f8301169050919050565b60006139bc8261395a565b6139c68185613965565b93506139d6818560208601613976565b6139df816139a0565b840191505092915050565b60006020820190508181036000830152613a0481846139b1565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a3782613a0c565b9050919050565b613a4781613a2c565b82525050565b6000602082019050613a626000830184613a3e565b92915050565b613a7181613a2c565b8114613a7c57600080fd5b50565b600081359050613a8e81613a68565b92915050565b60008060408385031215613aab57613aaa613832565b5b6000613ab985828601613a7f565b9250506020613aca85828601613918565b9150509250929050565b613add816138f7565b82525050565b6000602082019050613af86000830184613ad4565b92915050565b600080600060608486031215613b1757613b16613832565b5b6000613b2586828701613a7f565b9350506020613b3686828701613a7f565b9250506040613b4786828701613918565b9150509250925092565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b8e826139a0565b810181811067ffffffffffffffff82111715613bad57613bac613b56565b5b80604052505050565b6000613bc0613828565b9050613bcc8282613b85565b919050565b600067ffffffffffffffff821115613bec57613beb613b56565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b613c1581613c02565b8114613c2057600080fd5b50565b600081359050613c3281613c0c565b92915050565b6000613c4b613c4684613bd1565b613bb6565b90508083825260208201905060208402830185811115613c6e57613c6d613bfd565b5b835b81811015613c975780613c838882613c23565b845260208401935050602081019050613c70565b5050509392505050565b600082601f830112613cb657613cb5613b51565b5b8135613cc6848260208601613c38565b91505092915050565b600060208284031215613ce557613ce4613832565b5b600082013567ffffffffffffffff811115613d0357613d02613837565b5b613d0f84828501613ca1565b91505092915050565b600060208284031215613d2e57613d2d613832565b5b6000613d3c84828501613a7f565b91505092915050565b600080fd5b600067ffffffffffffffff821115613d6557613d64613b56565b5b613d6e826139a0565b9050602081019050919050565b82818337600083830152505050565b6000613d9d613d9884613d4a565b613bb6565b905082815260208101848484011115613db957613db8613d45565b5b613dc4848285613d7b565b509392505050565b600082601f830112613de157613de0613b51565b5b8135613df1848260208601613d8a565b91505092915050565b600060208284031215613e1057613e0f613832565b5b600082013567ffffffffffffffff811115613e2e57613e2d613837565b5b613e3a84828501613dcc565b91505092915050565b60048110613e5057600080fd5b50565b600081359050613e6281613e43565b92915050565b600060208284031215613e7e57613e7d613832565b5b6000613e8c84828501613e53565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110613ed557613ed4613e95565b5b50565b6000819050613ee682613ec4565b919050565b6000613ef682613ed8565b9050919050565b613f0681613eeb565b82525050565b6000602082019050613f216000830184613efd565b92915050565b613f30816138c1565b8114613f3b57600080fd5b50565b600081359050613f4d81613f27565b92915050565b60008060408385031215613f6a57613f69613832565b5b6000613f7885828601613a7f565b9250506020613f8985828601613f3e565b9150509250929050565b600067ffffffffffffffff821115613fae57613fad613b56565b5b613fb7826139a0565b9050602081019050919050565b6000613fd7613fd284613f93565b613bb6565b905082815260208101848484011115613ff357613ff2613d45565b5b613ffe848285613d7b565b509392505050565b600082601f83011261401b5761401a613b51565b5b813561402b848260208601613fc4565b91505092915050565b6000806000806080858703121561404e5761404d613832565b5b600061405c87828801613a7f565b945050602061406d87828801613a7f565b935050604061407e87828801613918565b925050606085013567ffffffffffffffff81111561409f5761409e613837565b5b6140ab87828801614006565b91505092959194509250565b600080604083850312156140ce576140cd613832565b5b60006140dc85828601613918565b92505060206140ed85828601613a7f565b9150509250929050565b6000806040838503121561410e5761410d613832565b5b600061411c85828601613a7f565b925050602061412d85828601613a7f565b9150509250929050565b60006020828403121561414d5761414c613832565b5b600061415b84828501613c23565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806141ab57607f821691505b6020821081036141be576141bd614164565b5b50919050565b60006060820190506141d96000830186613a3e565b6141e66020830185613a3e565b6141f36040830184613ad4565b949350505050565b60006040820190506142106000830185613a3e565b61421d6020830184613a3e565b9392505050565b60008151905061423381613f27565b92915050565b60006020828403121561424f5761424e613832565b5b600061425d84828501614224565b91505092915050565b7f4e6f20736d61727420636f6e7472616374732061726520616c6c6f7765640000600082015250565b600061429c601e83613965565b91506142a782614266565b602082019050919050565b600060208201905081810360008301526142cb8161428f565b9050919050565b7f53616c65206e6f74206163746976650000000000000000000000000000000000600082015250565b6000614308600f83613965565b9150614313826142d2565b602082019050919050565b60006020820190508181036000830152614337816142fb565b9050919050565b60008160601b9050919050565b60006143568261433e565b9050919050565b60006143688261434b565b9050919050565b61438061437b82613a2c565b61435d565b82525050565b6000614392828461436f565b60148201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006143db826138f7565b91506143e6836138f7565b92508282019050808211156143fe576143fd6143a1565b5b92915050565b7f4578636565647320737570706c79000000000000000000000000000000000000600082015250565b600061443a600e83613965565b915061444582614404565b602082019050919050565b600060208201905081810360008301526144698161442d565b9050919050565b7f45746865722073656e74206973206e6f7420636f727265637400000000000000600082015250565b60006144a6601983613965565b91506144b182614470565b602082019050919050565b600060208201905081810360008301526144d581614499565b9050919050565b60006040820190506144f16000830185613a3e565b6144fe6020830184613ad4565b9392505050565b6000614510826138f7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614542576145416143a1565b5b600182019050919050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2063757272656e7420737570706c7900000000000000000000000000000000602082015250565b60006145a9603083613965565b91506145b48261454d565b604082019050919050565b600060208201905081810360008301526145d88161459c565b9050919050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2070726576696f7573206d617820737570706c790000000000000000000000602082015250565b600061463b603583613965565b9150614646826145df565b604082019050919050565b6000602082019050818103600083015261466a8161462e565b9050919050565b600061467c826138f7565b9150614687836138f7565b925082820390508181111561469f5761469e6143a1565b5b92915050565b600081905092915050565b60008190508160005260206000209050919050565b600081546146d281614193565b6146dc81866146a5565b945060018216600081146146f7576001811461470c5761473f565b60ff198316865281151582028601935061473f565b614715856146b0565b60005b8381101561473757815481890152600182019150602081019050614718565b838801955050505b50505092915050565b60006147538261395a565b61475d81856146a5565b935061476d818560208601613976565b80840191505092915050565b600061478582856146c5565b91506147918284614748565b91508190509392505050565b7f45786365656473206d696e74207065722077616c6c6574000000000000000000600082015250565b60006147d3601783613965565b91506147de8261479d565b602082019050919050565b60006020820190508181036000830152614802816147c6565b9050919050565b6000614814826138f7565b915061481f836138f7565b925082820261482d816138f7565b91508282048414831517614844576148436143a1565b5b5092915050565b7f4e6f2062616c616e636520746f20776974686472617700000000000000000000600082015250565b6000614881601683613965565b915061488c8261484b565b602082019050919050565b600060208201905081810360008301526148b081614874565b9050919050565b7f416d6f756e74206973206e6f742076616c696400000000000000000000000000600082015250565b60006148ed601383613965565b91506148f8826148b7565b602082019050919050565b6000602082019050818103600083015261491c816148e0565b9050919050565b600081905092915050565b50565b600061493e600083614923565b91506149498261492e565b600082019050919050565b600061495f82614931565b9150819050919050565b7f5472616e73616374696f6e206661696c65640000000000000000000000000000600082015250565b600061499f601283613965565b91506149aa82614969565b602082019050919050565b600060208201905081810360008301526149ce81614992565b9050919050565b60006149e0826138f7565b9150600082036149f3576149f26143a1565b5b600182039050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020601f8301049050919050565b600082821b905092915050565b600060088302614a7a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614a3d565b614a848683614a3d565b95508019841693508086168417925050509392505050565b6000819050919050565b6000614ac1614abc614ab7846138f7565b614a9c565b6138f7565b9050919050565b6000819050919050565b614adb83614aa6565b614aef614ae782614ac8565b848454614a4a565b825550505050565b600090565b614b04614af7565b614b0f818484614ad2565b505050565b5b81811015614b3357614b28600082614afc565b600181019050614b15565b5050565b601f821115614b7857614b49816146b0565b614b5284614a2d565b81016020851015614b61578190505b614b75614b6d85614a2d565b830182614b14565b50505b505050565b600082821c905092915050565b6000614b9b60001984600802614b7d565b1980831691505092915050565b6000614bb48383614b8a565b9150826002028217905092915050565b614bcd8261395a565b67ffffffffffffffff811115614be657614be5613b56565b5b614bf08254614193565b614bfb828285614b37565b600060209050601f831160018114614c2e5760008415614c1c578287015190505b614c268582614ba8565b865550614c8e565b601f198416614c3c866146b0565b60005b82811015614c6457848901518255600182019150602085019450602081019050614c3f565b86831015614c815784890151614c7d601f891682614b8a565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614cd0826138f7565b9150614cdb836138f7565b925082614ceb57614cea614c96565b5b828204905092915050565b6000614d01826138f7565b9150614d0c836138f7565b925082614d1c57614d1b614c96565b5b828206905092915050565b600081519050919050565b600082825260208201905092915050565b6000614d4e82614d27565b614d588185614d32565b9350614d68818560208601613976565b614d71816139a0565b840191505092915050565b6000608082019050614d916000830187613a3e565b614d9e6020830186613a3e565b614dab6040830185613ad4565b8181036060830152614dbd8184614d43565b905095945050505050565b600081519050614dd781613868565b92915050565b600060208284031215614df357614df2613832565b5b6000614e0184828501614dc8565b9150509291505056fea2646970667358221220ff14bd865b00fa40770dcc60e989ad61973c8b2b0c621a86db37e1f3ba25422964736f6c63430008110033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000a556e646561644368656600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b554e4445414443484546530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040697066733a2f2f516d614c484d7162626438594e5934787a4b7458596843506654764b5755794d4d6f72566155347838456f69746e2f70726572657665616c2f

-----Decoded View---------------
Arg [0] : name_ (string): UndeadChef
Arg [1] : symbol_ (string): UNDEADCHEFS
Arg [2] : baseURI_ (string): ipfs://QmaLHMqbbd8YNY4xzKtXYhCPfTvKWUyMMorVaU4x8Eoitn/prereveal/

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [4] : 556e646561644368656600000000000000000000000000000000000000000000
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [6] : 554e444541444348454653000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [8] : 697066733a2f2f516d614c484d7162626438594e5934787a4b74585968435066
Arg [9] : 54764b5755794d4d6f72566155347838456f69746e2f70726572657665616c2f


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ 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.