ETH Price: $3,526.83 (+6.96%)

Token

Pepecoin x Frens (PEPECOINCOLLABS)
 

Overview

Max Total Supply

3,071 PEPECOINCOLLABS

Holders

1,402

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
0x92448e128010f55662c42bc2f549482964575acc
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
PepecoinXFrens

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 15 : PepeXFrens2.sol
// SPDX-License-Identifier: Frensware
// Factory contract for the Pepecoin x Frens collaboration collection

pragma solidity ^0.8.20;

import {ERC1155} from "@rari-capital/solmate/src/tokens/ERC1155.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {IERC1155MetadataURI} from "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Counters} from "@openzeppelin/contracts/utils/Counters.sol";


contract PepecoinXFrens is ERC1155, Ownable, Pausable, ReentrancyGuard {
    using Counters for Counters.Counter;
    using Strings for uint256;

    Counters.Counter private _tokenIds;

    string private contractMetadataURI;
    string private _name;
    string private _symbol;
    string private baseURI;

    mapping(uint256 => bytes32) public merkleRoots;
    mapping(uint256 => string) private tokenURIs;
    mapping(uint256 => uint256) public maxSupply;
    mapping(uint256 => uint256) public totalSupply;
    mapping(uint256 => uint256) public mintFees;

        enum TokenAvailability { CLAIM_ONLY, MINT_ONLY, BOTH }
    mapping(uint256 => TokenAvailability) public tokenAvailability;

    mapping(uint256 => bool) public isFrozen;
    mapping(uint256 => mapping(address => bool)) public whitelist;
    mapping(address => mapping(uint256 => bool)) private _hasClaimed;

    event tokenMinted(
        address indexed account,
        uint256 indexed id,
        uint256 amount
    );

    constructor(
        string memory name_,
        string memory symbol_,
        address initialOwner
    ) ERC1155() Ownable(initialOwner) {
        _name = name_;
        _symbol = symbol_;
        transferOwnership(initialOwner);
    }

function claim(uint256 id, bytes32[] calldata merkleProof)
    external
    nonReentrant
{
    require(tokenAvailability[id] == TokenAvailability.CLAIM_ONLY || tokenAvailability[id] == TokenAvailability.BOTH, "Token not available for claiming");
    require(!_hasClaimed[msg.sender][id], "NFT already claimed");
    require(totalSupply[id] < maxSupply[id], "Max supply reached");
    bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
    require(
        MerkleProof.verify(merkleProof, merkleRoots[id], leaf),
        "Invalid proof"
    );
    _hasClaimed[msg.sender][id] = true;
    _mint(msg.sender, id, 1, "");
    totalSupply[id] += 1;
    emit tokenMinted(msg.sender, id, 1);
}


function mint(uint256 id, uint256 amount)
    external payable
    nonReentrant
{
    require(tokenAvailability[id] == TokenAvailability.MINT_ONLY || tokenAvailability[id] == TokenAvailability.BOTH, "Token not available for minting");
    require(!isFrozen[id], "Token is frozen");
    require(
        totalSupply[id] + amount <= maxSupply[id],
        "Exceeds max supply"
    );
    uint256 requiredFee = mintFees[id] * amount;
    require(msg.value >= requiredFee, "Insufficient fee");

    _mint(msg.sender, id, amount, "");
    totalSupply[id] += amount;
    emit tokenMinted(msg.sender, id, amount);
}


function introduceNewToken(
    uint256 initialOwnerAmount,
    uint256 newMaxSupply,
    string calldata newURI,
    bytes32 newMerkleRoot,
    uint256 newMintFee,
    TokenAvailability availabilityMode 
) external onlyOwner {
    _tokenIds.increment();
    uint256 newTokenId = _tokenIds.current();

    require(bytes(newURI).length > 0, "URI must be set");
    require(initialOwnerAmount <= newMaxSupply, "Initial amount cannot exceed max supply");

    tokenURIs[newTokenId] = newURI;
    merkleRoots[newTokenId] = newMerkleRoot;
    mintFees[newTokenId] = newMintFee;
    maxSupply[newTokenId] = newMaxSupply;
    tokenAvailability[newTokenId] = availabilityMode; 

    if (initialOwnerAmount > 0) {
        _mint(owner(), newTokenId, initialOwnerAmount, "");
        totalSupply[newTokenId] = initialOwnerAmount;
    }
}

   function setTokenAvailability(uint256 tokenId, TokenAvailability availabilityMode)
        external onlyOwner {
        require(!isFrozen[tokenId], "Token is frozen");
        tokenAvailability[tokenId] = availabilityMode;
    }


    function setBaseURI(string memory newBaseURI) 
        public onlyOwner {
        baseURI = newBaseURI;
    }

    function uri(uint256 id)
        public
        view
        virtual
        override
        returns (string memory)
    {
        return tokenURIs[id];
    }

    function batchAddToWhitelist(uint256 tokenId, address[] calldata addresses)
        public onlyOwner {
        require(!isFrozen[tokenId], "Token frozen");
        for (uint256 i = 0; i < addresses.length; i++) {
            whitelist[tokenId][addresses[i]] = true;
        }
    }

    function basedUri(uint256 id) 
        public view returns (string memory) {
        require(bytes(baseURI).length > 0, "baseURI not set");
        return string(abi.encodePacked(baseURI, id.toString(), ".json"));
    }

    function contractURI() 
        public view returns (string memory) {
        return contractMetadataURI;
    }

    function setContractURI(string memory newContractURI) 
        public onlyOwner {
        contractMetadataURI = newContractURI;
    }

    function updateTokenURI(uint256 tokenId, string calldata newURI)
        external onlyOwner {
        tokenURIs[tokenId] = newURI;
    }

    function freeze(uint256 tokenId) 
        public onlyOwner {
        require(!isFrozen[tokenId], "ID already frozen");
        isFrozen[tokenId] = true;
    }

    function getUserBalances(address user)
        public view returns (uint256[] memory, uint256[] memory) {
        uint256 tokenCount = _tokenIds.current();
        uint256[] memory ids = new uint256[](tokenCount);
        uint256[] memory balances = new uint256[](tokenCount);

        for (uint256 i = 0; i < tokenCount; i++) {
            uint256 balance = balanceOf[user][i];
            if (balance > 0) {
                ids[i] = i;
                balances[i] = balance;
            }
        }

        return (ids, balances);
    }

    function eligibleForClaim(
        uint256 id,
        address user,
        bytes32[] calldata merkleProof
    ) external view returns (bool) {
        if (_hasClaimed[user][id]) {
            return false; // Has already claimed
        }
        bytes32 leaf = keccak256(abi.encodePacked(user));
        return MerkleProof.verify(merkleProof, merkleRoots[id], leaf);
    }

    function whitelistClaim(uint256 tokenId) 
        external nonReentrant {
        require(whitelist[tokenId][msg.sender], "Not whitelisted");
        require(!_hasClaimed[msg.sender][tokenId], "Already claimed");
        require(totalSupply[tokenId] < maxSupply[tokenId], "Max supply reached");

        _hasClaimed[msg.sender][tokenId] = true;
        _mint(msg.sender, tokenId, 1, "");
        totalSupply[tokenId] += 1;
        emit tokenMinted(msg.sender, tokenId, 1);
    }


    function burn(
        address account,
        uint256 id,
        uint256 amount
    ) public {
        require(
            account == msg.sender || isApprovedForAll[account][msg.sender],
            "Caller is not owner nor approved"
        );
        require(
            balanceOf[account][id] >= amount,
            "Burn amount exceeds balance"
        );

        _burn(account, id, amount); // Use the internal _burn function
        totalSupply[id] -= amount;
        emit TransferSingle(msg.sender, account, address(0), id, amount);
    }

    function setMerkleRoot(uint256 id, bytes32 newMerkleRoot)
        external
        onlyOwner {
        merkleRoots[id] = newMerkleRoot;
    }

    function name() 
        public view returns (string memory) {
        return _name;
    }

    function symbol()
        public
                view returns (string memory) {
        return _symbol;
    }

    function mailbox() 
        external onlyOwner nonReentrant {
        uint256 balance = address(this).balance;
        require(balance > 0, "No ETH to withdraw");
        payable(owner()).transfer(balance);
    }


function setApprovalForAll(address operator, bool approved)
    public
    override(ERC1155) {
    super.setApprovalForAll(operator, approved);
}


function supportsInterface(bytes4 interfaceId)
    public
    view
    override(ERC1155)
    returns (bool) {
    return super.supportsInterface(interfaceId);
}
}

File 2 of 15 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 3 of 15 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 15 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 5 of 15 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

File 6 of 15 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.20;

/**
 * @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 The multiproof provided is not valid.
     */
    error MerkleProofInvalidMultiproof();

    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     */
    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.
     */
    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}
     */
    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.
     */
    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.
     */
    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).
     */
    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.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](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) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            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.
     */
    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.
        if (leavesLen + proofLen != totalHashes + 1) {
            revert MerkleProofInvalidMultiproof();
        }

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](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) {
            if (proofPos != proofLen) {
                revert MerkleProofInvalidMultiproof();
            }
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Sorts the pair (a, b) and hashes the result.
     */
    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    /**
     * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
     */
    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 7 of 15 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

File 8 of 15 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 9 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 10 of 15 : ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*//////////////////////////////////////////////////////////////
                             ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                              ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        // Storing these outside the loop saves ~15 gas per iteration.
        uint256 id;
        uint256 amount;

        for (uint256 i = 0; i < ids.length; ) {
            id = ids[i];
            amount = amounts[i];

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

File 11 of 15 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

File 12 of 15 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 13 of 15 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the value of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata ids
    ) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
     * Ensure to follow the checks-effects-interactions pattern and consider employing
     * reentrancy guards when interacting with untrusted contracts.
     *
     * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
     *
     * Requirements:
     *
     * - `ids` and `values` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external;
}

File 14 of 15 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 15 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tokenMinted","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"basedUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"batchAddToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"eligibleForClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"freeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserBalances","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialOwnerAmount","type":"uint256"},{"internalType":"uint256","name":"newMaxSupply","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"uint256","name":"newMintFee","type":"uint256"},{"internalType":"enum PepecoinXFrens.TokenAvailability","name":"availabilityMode","type":"uint8"}],"name":"introduceNewToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mailbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"merkleRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mintFees","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":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","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":"newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newContractURI","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"enum PepecoinXFrens.TokenAvailability","name":"availabilityMode","type":"uint8"}],"name":"setTokenAvailability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenAvailability","outputs":[{"internalType":"enum PepecoinXFrens.TokenAvailability","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"}],"name":"updateTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"whitelistClaim","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801562000010575f80fd5b5060405162005d1c38038062005d1c83398181016040528101906200003691906200052d565b805f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000aa575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000a19190620005d5565b60405180910390fd5b620000bb816200011c60201b60201c565b505f600260146101000a81548160ff02191690831515021790555060016003819055508260069081620000ef919062000827565b50816007908162000101919062000827565b506200011381620001df60201b60201c565b5050506200090b565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620001ef6200027660201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000262575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620002599190620005d5565b60405180910390fd5b62000273816200011c60201b60201c565b50565b620002866200031860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620002ac6200031f60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200031657620002d86200031860201b60201c565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016200030d9190620005d5565b60405180910390fd5b565b5f33905090565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b620003a88262000360565b810181811067ffffffffffffffff82111715620003ca57620003c962000370565b5b80604052505050565b5f620003de62000347565b9050620003ec82826200039d565b919050565b5f67ffffffffffffffff8211156200040e576200040d62000370565b5b620004198262000360565b9050602081019050919050565b5f5b838110156200044557808201518184015260208101905062000428565b5f8484015250505050565b5f620004666200046084620003f1565b620003d3565b9050828152602081018484840111156200048557620004846200035c565b5b6200049284828562000426565b509392505050565b5f82601f830112620004b157620004b062000358565b5b8151620004c384826020860162000450565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620004f782620004cc565b9050919050565b6200050981620004eb565b811462000514575f80fd5b50565b5f815190506200052781620004fe565b92915050565b5f805f6060848603121562000547576200054662000350565b5b5f84015167ffffffffffffffff81111562000567576200056662000354565b5b62000575868287016200049a565b935050602084015167ffffffffffffffff81111562000599576200059862000354565b5b620005a7868287016200049a565b9250506040620005ba8682870162000517565b9150509250925092565b620005cf81620004eb565b82525050565b5f602082019050620005ea5f830184620005c4565b92915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200063f57607f821691505b602082108103620006555762000654620005fa565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620006b97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200067c565b620006c586836200067c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200070f620007096200070384620006dd565b620006e6565b620006dd565b9050919050565b5f819050919050565b6200072a83620006ef565b62000742620007398262000716565b84845462000688565b825550505050565b5f90565b620007586200074a565b620007658184846200071f565b505050565b5b818110156200078c57620007805f826200074e565b6001810190506200076b565b5050565b601f821115620007db57620007a5816200065b565b620007b0846200066d565b81016020851015620007c0578190505b620007d8620007cf856200066d565b8301826200076a565b50505b505050565b5f82821c905092915050565b5f620007fd5f1984600802620007e0565b1980831691505092915050565b5f620008178383620007ec565b9150826002028217905092915050565b6200083282620005f0565b67ffffffffffffffff8111156200084e576200084d62000370565b5b6200085a825462000627565b6200086782828562000790565b5f60209050601f8311600181146200089d575f841562000888578287015190505b6200089485826200080a565b86555062000903565b601f198416620008ad866200065b565b5f5b82811015620008d657848901518255600182019150602085019450602081019050620008af565b86831015620008f65784890151620008f2601f891682620007ec565b8355505b6001600288020188555050505b505050505050565b61540380620009195f395ff3fe608060405260043610610223575f3560e01c806381b2c2b011610122578063bd85b039116100aa578063ec15a8901161006e578063ec15a89014610856578063f242432a1461087e578063f2fde38b146108a6578063f5298aca146108ce578063f649b7ff146108f657610223565b8063bd85b03914610776578063d5438eae146107b2578063d7a78db8146107c8578063e8a3d485146107f0578063e985e9c51461081a57610223565b806394ee5d62116100f157806394ee5d621461066f57806395d89b41146106ab578063a0894799146106d5578063a22cb46514610711578063abd3f6121461073957610223565b806381b2c2b0146105a5578063869f7594146105e15780638da5cb5b1461061d578063938e3d7b1461064757610223565b8063271cacbf116101b05780634f442306116101745780634f442306146104c557806355f804b3146105015780635c975abb14610529578063715018a61461055357806371c5ecb11461056957610223565b8063271cacbf146103d55780632eb2c2d6146103fd5780632f52ebb7146104255780634b25bfce1461044d5780634e1273f41461048957610223565b806318712c21116101f757806318712c211461030557806318e97fd11461032d5780631b2ef1ca1461035557806321b12b611461037157806322af00d41461039957610223565b8062fdd58e1461022757806301ffc9a71461026357806306fdde031461029f5780630e89341c146102c9575b5f80fd5b348015610232575f80fd5b5061024d60048036038101906102489190613396565b61091e565b60405161025a91906133e3565b60405180910390f35b34801561026e575f80fd5b5061028960048036038101906102849190613451565b61093d565b6040516102969190613496565b60405180910390f35b3480156102aa575f80fd5b506102b361094e565b6040516102c09190613539565b60405180910390f35b3480156102d4575f80fd5b506102ef60048036038101906102ea9190613559565b6109de565b6040516102fc9190613539565b60405180910390f35b348015610310575f80fd5b5061032b600480360381019061032691906135b7565b610a7f565b005b348015610338575f80fd5b50610353600480360381019061034e9190613656565b610aa1565b005b61036f600480360381019061036a91906136b3565b610acf565b005b34801561037c575f80fd5b5061039760048036038101906103929190613714565b610d74565b005b3480156103a4575f80fd5b506103bf60048036038101906103ba9190613559565b610e16565b6040516103cc91906133e3565b60405180910390f35b3480156103e0575f80fd5b506103fb60048036038101906103f691906137a7565b610e2b565b005b348015610408575f80fd5b50610423600480360381019061041e91906138ae565b610f42565b005b348015610430575f80fd5b5061044b600480360381019061044691906139da565b611388565b005b348015610458575f80fd5b50610473600480360381019061046e9190613a37565b611725565b6040516104809190613496565b60405180910390f35b348015610494575f80fd5b506104af60048036038101906104aa9190613a75565b61174f565b6040516104bc9190613baa565b60405180910390f35b3480156104d0575f80fd5b506104eb60048036038101906104e69190613559565b6118b3565b6040516104f89190613c3d565b60405180910390f35b34801561050c575f80fd5b5061052760048036038101906105229190613d7e565b6118d0565b005b348015610534575f80fd5b5061053d6118eb565b60405161054a9190613496565b60405180910390f35b34801561055e575f80fd5b50610567611901565b005b348015610574575f80fd5b5061058f600480360381019061058a9190613559565b611914565b60405161059c9190613dd4565b60405180910390f35b3480156105b0575f80fd5b506105cb60048036038101906105c69190613559565b611929565b6040516105d89190613539565b60405180910390f35b3480156105ec575f80fd5b5061060760048036038101906106029190613559565b6119ad565b60405161061491906133e3565b60405180910390f35b348015610628575f80fd5b506106316119c2565b60405161063e9190613dfc565b60405180910390f35b348015610652575f80fd5b5061066d60048036038101906106689190613d7e565b6119ea565b005b34801561067a575f80fd5b5061069560048036038101906106909190613e15565b611a05565b6040516106a29190613496565b60405180910390f35b3480156106b6575f80fd5b506106bf611afe565b6040516106cc9190613539565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f69190613559565b611b8e565b6040516107089190613496565b60405180910390f35b34801561071c575f80fd5b5061073760048036038101906107329190613eb0565b611bab565b005b348015610744575f80fd5b5061075f600480360381019061075a9190613eee565b611bb9565b60405161076d929190613f19565b60405180910390f35b348015610781575f80fd5b5061079c60048036038101906107979190613559565b611d26565b6040516107a991906133e3565b60405180910390f35b3480156107bd575f80fd5b506107c6611d3b565b005b3480156107d3575f80fd5b506107ee60048036038101906107e99190613559565b611de7565b005b3480156107fb575f80fd5b50610804611e79565b6040516108119190613539565b60405180910390f35b348015610825575f80fd5b50610840600480360381019061083b9190613f4e565b611f09565b60405161084d9190613496565b60405180910390f35b348015610861575f80fd5b5061087c60048036038101906108779190613559565b611f33565b005b348015610889575f80fd5b506108a4600480360381019061089f9190613f8c565b6121d2565b005b3480156108b1575f80fd5b506108cc60048036038101906108c79190613eee565b612571565b005b3480156108d9575f80fd5b506108f460048036038101906108ef9190614022565b6125f5565b005b348015610901575f80fd5b5061091c60048036038101906109179190614072565b612832565b005b5f602052815f5260405f20602052805f5260405f205f91509150505481565b5f610947826129be565b9050919050565b60606006805461095d90614149565b80601f016020809104026020016040519081016040528092919081815260200182805461098990614149565b80156109d45780601f106109ab576101008083540402835291602001916109d4565b820191905f5260205f20905b8154815290600101906020018083116109b757829003601f168201915b5050505050905090565b6060600a5f8381526020019081526020015f2080546109fc90614149565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2890614149565b8015610a735780601f10610a4a57610100808354040283529160200191610a73565b820191905f5260205f20905b815481529060010190602001808311610a5657829003601f168201915b50505050509050919050565b610a87612a4f565b8060095f8481526020019081526020015f20819055505050565b610aa9612a4f565b8181600a5f8681526020019081526020015f209182610ac9929190614320565b50505050565b610ad7612ad6565b60016002811115610aeb57610aea613bca565b5b600e5f8481526020019081526020015f205f9054906101000a900460ff166002811115610b1b57610b1a613bca565b5b1480610b675750600280811115610b3557610b34613bca565b5b600e5f8481526020019081526020015f205f9054906101000a900460ff166002811115610b6557610b64613bca565b5b145b610ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9d90614437565b60405180910390fd5b600f5f8381526020019081526020015f205f9054906101000a900460ff1615610c04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfb9061449f565b60405180910390fd5b600b5f8381526020019081526020015f205481600c5f8581526020019081526020015f2054610c3391906144ea565b1115610c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6b90614567565b60405180910390fd5b5f81600d5f8581526020019081526020015f2054610c929190614585565b905080341015610cd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cce90614610565b60405180910390fd5b610cf133848460405180602001604052805f815250612b25565b81600c5f8581526020019081526020015f205f828254610d1191906144ea565b92505081905550823373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb7484604051610d5f91906133e3565b60405180910390a350610d70612d65565b5050565b610d7c612a4f565b600f5f8381526020019081526020015f205f9054906101000a900460ff1615610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd19061449f565b60405180910390fd5b80600e5f8481526020019081526020015f205f6101000a81548160ff02191690836002811115610e0d57610e0c613bca565b5b02179055505050565b600d602052805f5260405f205f915090505481565b610e33612a4f565b600f5f8481526020019081526020015f205f9054906101000a900460ff1615610e91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8890614678565b60405180910390fd5b5f5b82829050811015610f3c57600160105f8681526020019081526020015f205f858585818110610ec557610ec4614696565b5b9050602002016020810190610eda9190613eee565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080610f34906146c3565b915050610e93565b50505050565b838390508686905014610f8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8190614754565b60405180910390fd5b8773ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611045575060015f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b611084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107b906147bc565b60405180910390fd5b5f805f5b88889050811015611198578888828181106110a6576110a5614696565b5b9050602002013592508686828181106110c2576110c1614696565b5b905060200201359150815f808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f82825461112591906147da565b92505081905550815f808c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f82825461118691906144ea565b92505081905550806001019050611088565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516112139493929190614875565b60405180910390a45f8973ffffffffffffffffffffffffffffffffffffffff163b1461130c5763bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168973ffffffffffffffffffffffffffffffffffffffff1663bc197c81338d8c8c8c8c8c8c6040518963ffffffff1660e01b81526004016112a79897969594939291906148ea565b6020604051808303815f875af11580156112c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112e7919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461133d565b5f73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b61137c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611373906149df565b60405180910390fd5b50505050505050505050565b611390612ad6565b5f60028111156113a3576113a2613bca565b5b600e5f8581526020019081526020015f205f9054906101000a900460ff1660028111156113d3576113d2613bca565b5b148061141f57506002808111156113ed576113ec613bca565b5b600e5f8581526020019081526020015f205f9054906101000a900460ff16600281111561141d5761141c613bca565b5b145b61145e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145590614a47565b60405180910390fd5b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900460ff16156114f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ee90614aaf565b60405180910390fd5b600b5f8481526020019081526020015f2054600c5f8581526020019081526020015f20541061155b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155290614b17565b60405180910390fd5b5f3360405160200161156d9190614b7a565b6040516020818303038152906040528051906020012090506115e18383808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f8201169050808301925050505050505060095f8781526020019081526020015f205483612d6f565b611620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161790614bde565b60405180910390fd5b600160115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f6101000a81548160ff02191690831515021790555061169f3385600160405180602001604052805f815250612b25565b6001600c5f8681526020019081526020015f205f8282546116c091906144ea565b92505081905550833373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb74600160405161170f9190614c35565b60405180910390a350611720612d65565b505050565b6010602052815f5260405f20602052805f5260405f205f915091509054906101000a900460ff1681565b6060828290508585905014611799576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179090614754565b60405180910390fd5b8484905067ffffffffffffffff8111156117b6576117b5613c5a565b5b6040519080825280602002602001820160405280156117e45781602001602082028036833780820191505090505b5090505f5b858590508110156118aa575f8087878481811061180957611808614696565b5b905060200201602081019061181e9190613eee565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f85858481811061186b5761186a614696565b5b9050602002013581526020019081526020015f205482828151811061189357611892614696565b5b6020026020010181815250508060010190506117e9565b50949350505050565b600e602052805f5260405f205f915054906101000a900460ff1681565b6118d8612a4f565b80600890816118e79190614c4e565b5050565b5f600260149054906101000a900460ff16905090565b611909612a4f565b6119125f612d85565b565b6009602052805f5260405f205f915090505481565b60605f6008805461193990614149565b90501161197b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197290614d67565b60405180910390fd5b600861198683612e48565b604051602001611997929190614e89565b6040516020818303038152906040529050919050565b600b602052805f5260405f205f915090505481565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6119f2612a4f565b8060059081611a019190614c4e565b5050565b5f60115f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f9054906101000a900460ff1615611a6c575f9050611af6565b5f84604051602001611a7e9190614b7a565b604051602081830303815290604052805190602001209050611af28484808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f8201169050808301925050505050505060095f8981526020019081526020015f205483612d6f565b9150505b949350505050565b606060078054611b0d90614149565b80601f0160208091040260200160405190810160405280929190818152602001828054611b3990614149565b8015611b845780601f10611b5b57610100808354040283529160200191611b84565b820191905f5260205f20905b815481529060010190602001808311611b6757829003601f168201915b5050505050905090565b600f602052805f5260405f205f915054906101000a900460ff1681565b611bb58282612f12565b5050565b6060805f611bc7600461300a565b90505f8167ffffffffffffffff811115611be457611be3613c5a565b5b604051908082528060200260200182016040528015611c125781602001602082028036833780820191505090505b5090505f8267ffffffffffffffff811115611c3057611c2f613c5a565b5b604051908082528060200260200182016040528015611c5e5781602001602082028036833780820191505090505b5090505f5b83811015611d17575f805f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205490505f811115611d035781848381518110611cd657611cd5614696565b5b60200260200101818152505080838381518110611cf657611cf5614696565b5b6020026020010181815250505b508080611d0f906146c3565b915050611c63565b50818194509450505050915091565b600c602052805f5260405f205f915090505481565b611d43612a4f565b611d4b612ad6565b5f4790505f8111611d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8890614f01565b60405180910390fd5b611d996119c2565b73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611ddb573d5f803e3d5ffd5b5050611de5612d65565b565b611def612a4f565b600f5f8281526020019081526020015f205f9054906101000a900460ff1615611e4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4490614f69565b60405180910390fd5b6001600f5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b606060058054611e8890614149565b80601f0160208091040260200160405190810160405280929190818152602001828054611eb490614149565b8015611eff5780601f10611ed657610100808354040283529160200191611eff565b820191905f5260205f20905b815481529060010190602001808311611ee257829003601f168201915b5050505050905090565b6001602052815f5260405f20602052805f5260405f205f915091509054906101000a900460ff1681565b611f3b612ad6565b60105f8281526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611fd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fca90614fd1565b60405180910390fd5b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f9054906101000a900460ff161561206c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206390615039565b60405180910390fd5b600b5f8281526020019081526020015f2054600c5f8381526020019081526020015f2054106120d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c790614b17565b60405180910390fd5b600160115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555061214f3382600160405180602001604052805f815250612b25565b6001600c5f8381526020019081526020015f205f82825461217091906144ea565b92505081905550803373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb7460016040516121bf9190614c35565b60405180910390a36121cf612d65565b50565b8573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061228d575060015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b6122cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c3906147bc565b60405180910390fd5b825f808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f82825461232691906147da565b92505081905550825f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f82825461238791906144ea565b925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612404929190615057565b60405180910390a45f8573ffffffffffffffffffffffffffffffffffffffff163b146124f95763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168573ffffffffffffffffffffffffffffffffffffffff1663f23a6e613389888888886040518763ffffffff1660e01b81526004016124949695949392919061507e565b6020604051808303815f875af11580156124b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124d4919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461252a565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b612569576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612560906149df565b60405180910390fd5b505050505050565b612579612a4f565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125e9575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016125e09190613dfc565b60405180910390fd5b6125f281612d85565b50565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806126b0575060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b6126ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e690615122565b60405180910390fd5b805f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2054101561277d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127749061518a565b60405180910390fd5b612788838383613016565b80600c5f8481526020019081526020015f205f8282546127a891906147da565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612825929190615057565b60405180910390a4505050565b61283a612a4f565b61284460046130fa565b5f61284f600461300a565b90505f8686905011612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d906151f2565b60405180910390fd5b868811156128d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128d090615280565b60405180910390fd5b8585600a5f8481526020019081526020015f2091826128f9929190614320565b508360095f8381526020019081526020015f208190555082600d5f8381526020019081526020015f208190555086600b5f8381526020019081526020015f208190555081600e5f8381526020019081526020015f205f6101000a81548160ff0219169083600281111561296f5761296e613bca565b5b02179055505f8811156129b45761299d6129876119c2565b828a60405180602001604052805f815250612b25565b87600c5f8381526020019081526020015f20819055505b5050505050505050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612a18575063d9b67a2660e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612a485750630e89341c60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b612a5761310e565b73ffffffffffffffffffffffffffffffffffffffff16612a756119c2565b73ffffffffffffffffffffffffffffffffffffffff1614612ad457612a9861310e565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612acb9190613dfc565b60405180910390fd5b565b600260035403612b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b12906152e8565b60405180910390fd5b6002600381905550565b815f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f828254612b7f91906144ea565b925050819055508373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628686604051612bfc929190615057565b60405180910390a45f8473ffffffffffffffffffffffffffffffffffffffff163b14612cef5763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663f23a6e61335f8787876040518663ffffffff1660e01b8152600401612c8a959493929190615348565b6020604051808303815f875af1158015612ca6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cca919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612d20565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b612d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d56906149df565b60405180910390fd5b50505050565b6001600381905550565b5f82612d7b8584613115565b1490509392505050565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60605f6001612e5684613169565b0190505f8167ffffffffffffffff811115612e7457612e73613c5a565b5b6040519080825280601f01601f191660200182016040528015612ea65781602001600182028036833780820191505090505b5090505f82602001820190505b600115612f07578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612efc57612efb6153a0565b5b0494505f8503612eb3575b819350505050919050565b8060015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612ffe9190613496565b60405180910390a35050565b5f815f01549050919050565b805f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f82825461307091906147da565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516130ed929190615057565b60405180910390a4505050565b6001815f015f828254019250508190555050565b5f33905090565b5f808290505f5b845181101561315e576131498286838151811061313c5761313b614696565b5b60200260200101516132ba565b91508080613156906146c3565b91505061311c565b508091505092915050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106131c5577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816131bb576131ba6153a0565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613202576d04ee2d6d415b85acef810000000083816131f8576131f76153a0565b5b0492506020810190505b662386f26fc10000831061323157662386f26fc100008381613227576132266153a0565b5b0492506010810190505b6305f5e100831061325a576305f5e10083816132505761324f6153a0565b5b0492506008810190505b612710831061327f576127108381613275576132746153a0565b5b0492506004810190505b606483106132a25760648381613298576132976153a0565b5b0492506002810190505b600a83106132b1576001810190505b80915050919050565b5f8183106132d1576132cc82846132e4565b6132dc565b6132db83836132e4565b5b905092915050565b5f825f528160205260405f20905092915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61333282613309565b9050919050565b61334281613328565b811461334c575f80fd5b50565b5f8135905061335d81613339565b92915050565b5f819050919050565b61337581613363565b811461337f575f80fd5b50565b5f813590506133908161336c565b92915050565b5f80604083850312156133ac576133ab613301565b5b5f6133b98582860161334f565b92505060206133ca85828601613382565b9150509250929050565b6133dd81613363565b82525050565b5f6020820190506133f65f8301846133d4565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613430816133fc565b811461343a575f80fd5b50565b5f8135905061344b81613427565b92915050565b5f6020828403121561346657613465613301565b5b5f6134738482850161343d565b91505092915050565b5f8115159050919050565b6134908161347c565b82525050565b5f6020820190506134a95f830184613487565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156134e65780820151818401526020810190506134cb565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61350b826134af565b61351581856134b9565b93506135258185602086016134c9565b61352e816134f1565b840191505092915050565b5f6020820190508181035f8301526135518184613501565b905092915050565b5f6020828403121561356e5761356d613301565b5b5f61357b84828501613382565b91505092915050565b5f819050919050565b61359681613584565b81146135a0575f80fd5b50565b5f813590506135b18161358d565b92915050565b5f80604083850312156135cd576135cc613301565b5b5f6135da85828601613382565b92505060206135eb858286016135a3565b9150509250929050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613616576136156135f5565b5b8235905067ffffffffffffffff811115613633576136326135f9565b5b60208301915083600182028301111561364f5761364e6135fd565b5b9250929050565b5f805f6040848603121561366d5761366c613301565b5b5f61367a86828701613382565b935050602084013567ffffffffffffffff81111561369b5761369a613305565b5b6136a786828701613601565b92509250509250925092565b5f80604083850312156136c9576136c8613301565b5b5f6136d685828601613382565b92505060206136e785828601613382565b9150509250929050565b600381106136fd575f80fd5b50565b5f8135905061370e816136f1565b92915050565b5f806040838503121561372a57613729613301565b5b5f61373785828601613382565b925050602061374885828601613700565b9150509250929050565b5f8083601f840112613767576137666135f5565b5b8235905067ffffffffffffffff811115613784576137836135f9565b5b6020830191508360208202830111156137a05761379f6135fd565b5b9250929050565b5f805f604084860312156137be576137bd613301565b5b5f6137cb86828701613382565b935050602084013567ffffffffffffffff8111156137ec576137eb613305565b5b6137f886828701613752565b92509250509250925092565b5f8083601f840112613819576138186135f5565b5b8235905067ffffffffffffffff811115613836576138356135f9565b5b602083019150836020820283011115613852576138516135fd565b5b9250929050565b5f8083601f84011261386e5761386d6135f5565b5b8235905067ffffffffffffffff81111561388b5761388a6135f9565b5b6020830191508360018202830111156138a7576138a66135fd565b5b9250929050565b5f805f805f805f8060a0898b0312156138ca576138c9613301565b5b5f6138d78b828c0161334f565b98505060206138e88b828c0161334f565b975050604089013567ffffffffffffffff81111561390957613908613305565b5b6139158b828c01613804565b9650965050606089013567ffffffffffffffff81111561393857613937613305565b5b6139448b828c01613804565b9450945050608089013567ffffffffffffffff81111561396757613966613305565b5b6139738b828c01613859565b92509250509295985092959890939650565b5f8083601f84011261399a576139996135f5565b5b8235905067ffffffffffffffff8111156139b7576139b66135f9565b5b6020830191508360208202830111156139d3576139d26135fd565b5b9250929050565b5f805f604084860312156139f1576139f0613301565b5b5f6139fe86828701613382565b935050602084013567ffffffffffffffff811115613a1f57613a1e613305565b5b613a2b86828701613985565b92509250509250925092565b5f8060408385031215613a4d57613a4c613301565b5b5f613a5a85828601613382565b9250506020613a6b8582860161334f565b9150509250929050565b5f805f8060408587031215613a8d57613a8c613301565b5b5f85013567ffffffffffffffff811115613aaa57613aa9613305565b5b613ab687828801613752565b9450945050602085013567ffffffffffffffff811115613ad957613ad8613305565b5b613ae587828801613804565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613b2581613363565b82525050565b5f613b368383613b1c565b60208301905092915050565b5f602082019050919050565b5f613b5882613af3565b613b628185613afd565b9350613b6d83613b0d565b805f5b83811015613b9d578151613b848882613b2b565b9750613b8f83613b42565b925050600181019050613b70565b5085935050505092915050565b5f6020820190508181035f830152613bc28184613b4e565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613c0857613c07613bca565b5b50565b5f819050613c1882613bf7565b919050565b5f613c2782613c0b565b9050919050565b613c3781613c1d565b82525050565b5f602082019050613c505f830184613c2e565b92915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613c90826134f1565b810181811067ffffffffffffffff82111715613caf57613cae613c5a565b5b80604052505050565b5f613cc16132f8565b9050613ccd8282613c87565b919050565b5f67ffffffffffffffff821115613cec57613ceb613c5a565b5b613cf5826134f1565b9050602081019050919050565b828183375f83830152505050565b5f613d22613d1d84613cd2565b613cb8565b905082815260208101848484011115613d3e57613d3d613c56565b5b613d49848285613d02565b509392505050565b5f82601f830112613d6557613d646135f5565b5b8135613d75848260208601613d10565b91505092915050565b5f60208284031215613d9357613d92613301565b5b5f82013567ffffffffffffffff811115613db057613daf613305565b5b613dbc84828501613d51565b91505092915050565b613dce81613584565b82525050565b5f602082019050613de75f830184613dc5565b92915050565b613df681613328565b82525050565b5f602082019050613e0f5f830184613ded565b92915050565b5f805f8060608587031215613e2d57613e2c613301565b5b5f613e3a87828801613382565b9450506020613e4b8782880161334f565b935050604085013567ffffffffffffffff811115613e6c57613e6b613305565b5b613e7887828801613985565b925092505092959194509250565b613e8f8161347c565b8114613e99575f80fd5b50565b5f81359050613eaa81613e86565b92915050565b5f8060408385031215613ec657613ec5613301565b5b5f613ed38582860161334f565b9250506020613ee485828601613e9c565b9150509250929050565b5f60208284031215613f0357613f02613301565b5b5f613f108482850161334f565b91505092915050565b5f6040820190508181035f830152613f318185613b4e565b90508181036020830152613f458184613b4e565b90509392505050565b5f8060408385031215613f6457613f63613301565b5b5f613f718582860161334f565b9250506020613f828582860161334f565b9150509250929050565b5f805f805f8060a08789031215613fa657613fa5613301565b5b5f613fb389828a0161334f565b9650506020613fc489828a0161334f565b9550506040613fd589828a01613382565b9450506060613fe689828a01613382565b935050608087013567ffffffffffffffff81111561400757614006613305565b5b61401389828a01613859565b92509250509295509295509295565b5f805f6060848603121561403957614038613301565b5b5f6140468682870161334f565b935050602061405786828701613382565b925050604061406886828701613382565b9150509250925092565b5f805f805f805f60c0888a03121561408d5761408c613301565b5b5f61409a8a828b01613382565b97505060206140ab8a828b01613382565b965050604088013567ffffffffffffffff8111156140cc576140cb613305565b5b6140d88a828b01613601565b955095505060606140eb8a828b016135a3565b93505060806140fc8a828b01613382565b92505060a061410d8a828b01613700565b91505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061416057607f821691505b6020821081036141735761417261411c565b5b50919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026141df7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826141a4565b6141e986836141a4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61422461421f61421a84613363565b614201565b613363565b9050919050565b5f819050919050565b61423d8361420a565b6142516142498261422b565b8484546141b0565b825550505050565b5f90565b614265614259565b614270818484614234565b505050565b5b81811015614293576142885f8261425d565b600181019050614276565b5050565b601f8211156142d8576142a981614183565b6142b284614195565b810160208510156142c1578190505b6142d56142cd85614195565b830182614275565b50505b505050565b5f82821c905092915050565b5f6142f85f19846008026142dd565b1980831691505092915050565b5f61431083836142e9565b9150826002028217905092915050565b61432a8383614179565b67ffffffffffffffff81111561434357614342613c5a565b5b61434d8254614149565b614358828285614297565b5f601f831160018114614385575f8415614373578287013590505b61437d8582614305565b8655506143e4565b601f19841661439386614183565b5f5b828110156143ba57848901358255600182019150602085019450602081019050614395565b868310156143d757848901356143d3601f8916826142e9565b8355505b6001600288020188555050505b50505050505050565b7f546f6b656e206e6f7420617661696c61626c6520666f72206d696e74696e67005f82015250565b5f614421601f836134b9565b915061442c826143ed565b602082019050919050565b5f6020820190508181035f83015261444e81614415565b9050919050565b7f546f6b656e2069732066726f7a656e00000000000000000000000000000000005f82015250565b5f614489600f836134b9565b915061449482614455565b602082019050919050565b5f6020820190508181035f8301526144b68161447d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144f482613363565b91506144ff83613363565b9250828201905080821115614517576145166144bd565b5b92915050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f6145516012836134b9565b915061455c8261451d565b602082019050919050565b5f6020820190508181035f83015261457e81614545565b9050919050565b5f61458f82613363565b915061459a83613363565b92508282026145a881613363565b915082820484148315176145bf576145be6144bd565b5b5092915050565b7f496e73756666696369656e7420666565000000000000000000000000000000005f82015250565b5f6145fa6010836134b9565b9150614605826145c6565b602082019050919050565b5f6020820190508181035f830152614627816145ee565b9050919050565b7f546f6b656e2066726f7a656e00000000000000000000000000000000000000005f82015250565b5f614662600c836134b9565b915061466d8261462e565b602082019050919050565b5f6020820190508181035f83015261468f81614656565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6146cd82613363565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146ff576146fe6144bd565b5b600182019050919050565b7f4c454e4754485f4d49534d4154434800000000000000000000000000000000005f82015250565b5f61473e600f836134b9565b91506147498261470a565b602082019050919050565b5f6020820190508181035f83015261476b81614732565b9050919050565b7f4e4f545f415554484f52495a45440000000000000000000000000000000000005f82015250565b5f6147a6600e836134b9565b91506147b182614772565b602082019050919050565b5f6020820190508181035f8301526147d38161479a565b9050919050565b5f6147e482613363565b91506147ef83613363565b9250828203905081811115614807576148066144bd565b5b92915050565b5f80fd5b82818337505050565b5f6148258385613afd565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156148585761485761480d565b5b602083029250614869838584614811565b82840190509392505050565b5f6040820190508181035f83015261488e81868861481a565b905081810360208301526148a381848661481a565b905095945050505050565b5f82825260208201905092915050565b5f6148c983856148ae565b93506148d6838584613d02565b6148df836134f1565b840190509392505050565b5f60a0820190506148fd5f83018b613ded565b61490a602083018a613ded565b818103604083015261491d81888a61481a565b9050818103606083015261493281868861481a565b905081810360808301526149478184866148be565b90509998505050505050505050565b5f8151905061496481613427565b92915050565b5f6020828403121561497f5761497e613301565b5b5f61498c84828501614956565b91505092915050565b7f554e534146455f524543495049454e54000000000000000000000000000000005f82015250565b5f6149c96010836134b9565b91506149d482614995565b602082019050919050565b5f6020820190508181035f8301526149f6816149bd565b9050919050565b7f546f6b656e206e6f7420617661696c61626c6520666f7220636c61696d696e675f82015250565b5f614a316020836134b9565b9150614a3c826149fd565b602082019050919050565b5f6020820190508181035f830152614a5e81614a25565b9050919050565b7f4e465420616c726561647920636c61696d6564000000000000000000000000005f82015250565b5f614a996013836134b9565b9150614aa482614a65565b602082019050919050565b5f6020820190508181035f830152614ac681614a8d565b9050919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f614b016012836134b9565b9150614b0c82614acd565b602082019050919050565b5f6020820190508181035f830152614b2e81614af5565b9050919050565b5f8160601b9050919050565b5f614b4b82614b35565b9050919050565b5f614b5c82614b41565b9050919050565b614b74614b6f82613328565b614b52565b82525050565b5f614b858284614b63565b60148201915081905092915050565b7f496e76616c69642070726f6f66000000000000000000000000000000000000005f82015250565b5f614bc8600d836134b9565b9150614bd382614b94565b602082019050919050565b5f6020820190508181035f830152614bf581614bbc565b9050919050565b5f819050919050565b5f614c1f614c1a614c1584614bfc565b614201565b613363565b9050919050565b614c2f81614c05565b82525050565b5f602082019050614c485f830184614c26565b92915050565b614c57826134af565b67ffffffffffffffff811115614c7057614c6f613c5a565b5b614c7a8254614149565b614c85828285614297565b5f60209050601f831160018114614cb6575f8415614ca4578287015190505b614cae8582614305565b865550614d15565b601f198416614cc486614183565b5f5b82811015614ceb57848901518255600182019150602085019450602081019050614cc6565b86831015614d085784890151614d04601f8916826142e9565b8355505b6001600288020188555050505b505050505050565b7f62617365555249206e6f742073657400000000000000000000000000000000005f82015250565b5f614d51600f836134b9565b9150614d5c82614d1d565b602082019050919050565b5f6020820190508181035f830152614d7e81614d45565b9050919050565b5f81905092915050565b5f8154614d9b81614149565b614da58186614d85565b9450600182165f8114614dbf5760018114614dd457614e06565b60ff1983168652811515820286019350614e06565b614ddd85614183565b5f5b83811015614dfe57815481890152600182019150602081019050614ddf565b838801955050505b50505092915050565b5f614e19826134af565b614e238185614d85565b9350614e338185602086016134c9565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f614e73600583614d85565b9150614e7e82614e3f565b600582019050919050565b5f614e948285614d8f565b9150614ea08284614e0f565b9150614eab82614e67565b91508190509392505050565b7f4e6f2045544820746f20776974686472617700000000000000000000000000005f82015250565b5f614eeb6012836134b9565b9150614ef682614eb7565b602082019050919050565b5f6020820190508181035f830152614f1881614edf565b9050919050565b7f494420616c72656164792066726f7a656e0000000000000000000000000000005f82015250565b5f614f536011836134b9565b9150614f5e82614f1f565b602082019050919050565b5f6020820190508181035f830152614f8081614f47565b9050919050565b7f4e6f742077686974656c697374656400000000000000000000000000000000005f82015250565b5f614fbb600f836134b9565b9150614fc682614f87565b602082019050919050565b5f6020820190508181035f830152614fe881614faf565b9050919050565b7f416c726561647920636c61696d656400000000000000000000000000000000005f82015250565b5f615023600f836134b9565b915061502e82614fef565b602082019050919050565b5f6020820190508181035f83015261505081615017565b9050919050565b5f60408201905061506a5f8301856133d4565b61507760208301846133d4565b9392505050565b5f60a0820190506150915f830189613ded565b61509e6020830188613ded565b6150ab60408301876133d4565b6150b860608301866133d4565b81810360808301526150cb8184866148be565b9050979650505050505050565b7f43616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665645f82015250565b5f61510c6020836134b9565b9150615117826150d8565b602082019050919050565b5f6020820190508181035f83015261513981615100565b9050919050565b7f4275726e20616d6f756e7420657863656564732062616c616e636500000000005f82015250565b5f615174601b836134b9565b915061517f82615140565b602082019050919050565b5f6020820190508181035f8301526151a181615168565b9050919050565b7f555249206d7573742062652073657400000000000000000000000000000000005f82015250565b5f6151dc600f836134b9565b91506151e7826151a8565b602082019050919050565b5f6020820190508181035f830152615209816151d0565b9050919050565b7f496e697469616c20616d6f756e742063616e6e6f7420657863656564206d61785f8201527f20737570706c7900000000000000000000000000000000000000000000000000602082015250565b5f61526a6027836134b9565b915061527582615210565b604082019050919050565b5f6020820190508181035f8301526152978161525e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c005f82015250565b5f6152d2601f836134b9565b91506152dd8261529e565b602082019050919050565b5f6020820190508181035f8301526152ff816152c6565b9050919050565b5f81519050919050565b5f61531a82615306565b61532481856148ae565b93506153348185602086016134c9565b61533d816134f1565b840191505092915050565b5f60a08201905061535b5f830188613ded565b6153686020830187613ded565b61537560408301866133d4565b61538260608301856133d4565b81810360808301526153948184615310565b90509695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffdfea26469706673582212203308cc927bb7d837b8b0def943e234ae7a0ada6206ea1b60272533c1de09fe4c64736f6c63430008140033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000006942013379d195323e17cd2616435dce819c1fa9000000000000000000000000000000000000000000000000000000000000001050657065636f696e2078204672656e7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f50455045434f494e434f4c4c4142530000000000000000000000000000000000

Deployed Bytecode

0x608060405260043610610223575f3560e01c806381b2c2b011610122578063bd85b039116100aa578063ec15a8901161006e578063ec15a89014610856578063f242432a1461087e578063f2fde38b146108a6578063f5298aca146108ce578063f649b7ff146108f657610223565b8063bd85b03914610776578063d5438eae146107b2578063d7a78db8146107c8578063e8a3d485146107f0578063e985e9c51461081a57610223565b806394ee5d62116100f157806394ee5d621461066f57806395d89b41146106ab578063a0894799146106d5578063a22cb46514610711578063abd3f6121461073957610223565b806381b2c2b0146105a5578063869f7594146105e15780638da5cb5b1461061d578063938e3d7b1461064757610223565b8063271cacbf116101b05780634f442306116101745780634f442306146104c557806355f804b3146105015780635c975abb14610529578063715018a61461055357806371c5ecb11461056957610223565b8063271cacbf146103d55780632eb2c2d6146103fd5780632f52ebb7146104255780634b25bfce1461044d5780634e1273f41461048957610223565b806318712c21116101f757806318712c211461030557806318e97fd11461032d5780631b2ef1ca1461035557806321b12b611461037157806322af00d41461039957610223565b8062fdd58e1461022757806301ffc9a71461026357806306fdde031461029f5780630e89341c146102c9575b5f80fd5b348015610232575f80fd5b5061024d60048036038101906102489190613396565b61091e565b60405161025a91906133e3565b60405180910390f35b34801561026e575f80fd5b5061028960048036038101906102849190613451565b61093d565b6040516102969190613496565b60405180910390f35b3480156102aa575f80fd5b506102b361094e565b6040516102c09190613539565b60405180910390f35b3480156102d4575f80fd5b506102ef60048036038101906102ea9190613559565b6109de565b6040516102fc9190613539565b60405180910390f35b348015610310575f80fd5b5061032b600480360381019061032691906135b7565b610a7f565b005b348015610338575f80fd5b50610353600480360381019061034e9190613656565b610aa1565b005b61036f600480360381019061036a91906136b3565b610acf565b005b34801561037c575f80fd5b5061039760048036038101906103929190613714565b610d74565b005b3480156103a4575f80fd5b506103bf60048036038101906103ba9190613559565b610e16565b6040516103cc91906133e3565b60405180910390f35b3480156103e0575f80fd5b506103fb60048036038101906103f691906137a7565b610e2b565b005b348015610408575f80fd5b50610423600480360381019061041e91906138ae565b610f42565b005b348015610430575f80fd5b5061044b600480360381019061044691906139da565b611388565b005b348015610458575f80fd5b50610473600480360381019061046e9190613a37565b611725565b6040516104809190613496565b60405180910390f35b348015610494575f80fd5b506104af60048036038101906104aa9190613a75565b61174f565b6040516104bc9190613baa565b60405180910390f35b3480156104d0575f80fd5b506104eb60048036038101906104e69190613559565b6118b3565b6040516104f89190613c3d565b60405180910390f35b34801561050c575f80fd5b5061052760048036038101906105229190613d7e565b6118d0565b005b348015610534575f80fd5b5061053d6118eb565b60405161054a9190613496565b60405180910390f35b34801561055e575f80fd5b50610567611901565b005b348015610574575f80fd5b5061058f600480360381019061058a9190613559565b611914565b60405161059c9190613dd4565b60405180910390f35b3480156105b0575f80fd5b506105cb60048036038101906105c69190613559565b611929565b6040516105d89190613539565b60405180910390f35b3480156105ec575f80fd5b5061060760048036038101906106029190613559565b6119ad565b60405161061491906133e3565b60405180910390f35b348015610628575f80fd5b506106316119c2565b60405161063e9190613dfc565b60405180910390f35b348015610652575f80fd5b5061066d60048036038101906106689190613d7e565b6119ea565b005b34801561067a575f80fd5b5061069560048036038101906106909190613e15565b611a05565b6040516106a29190613496565b60405180910390f35b3480156106b6575f80fd5b506106bf611afe565b6040516106cc9190613539565b60405180910390f35b3480156106e0575f80fd5b506106fb60048036038101906106f69190613559565b611b8e565b6040516107089190613496565b60405180910390f35b34801561071c575f80fd5b5061073760048036038101906107329190613eb0565b611bab565b005b348015610744575f80fd5b5061075f600480360381019061075a9190613eee565b611bb9565b60405161076d929190613f19565b60405180910390f35b348015610781575f80fd5b5061079c60048036038101906107979190613559565b611d26565b6040516107a991906133e3565b60405180910390f35b3480156107bd575f80fd5b506107c6611d3b565b005b3480156107d3575f80fd5b506107ee60048036038101906107e99190613559565b611de7565b005b3480156107fb575f80fd5b50610804611e79565b6040516108119190613539565b60405180910390f35b348015610825575f80fd5b50610840600480360381019061083b9190613f4e565b611f09565b60405161084d9190613496565b60405180910390f35b348015610861575f80fd5b5061087c60048036038101906108779190613559565b611f33565b005b348015610889575f80fd5b506108a4600480360381019061089f9190613f8c565b6121d2565b005b3480156108b1575f80fd5b506108cc60048036038101906108c79190613eee565b612571565b005b3480156108d9575f80fd5b506108f460048036038101906108ef9190614022565b6125f5565b005b348015610901575f80fd5b5061091c60048036038101906109179190614072565b612832565b005b5f602052815f5260405f20602052805f5260405f205f91509150505481565b5f610947826129be565b9050919050565b60606006805461095d90614149565b80601f016020809104026020016040519081016040528092919081815260200182805461098990614149565b80156109d45780601f106109ab576101008083540402835291602001916109d4565b820191905f5260205f20905b8154815290600101906020018083116109b757829003601f168201915b5050505050905090565b6060600a5f8381526020019081526020015f2080546109fc90614149565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2890614149565b8015610a735780601f10610a4a57610100808354040283529160200191610a73565b820191905f5260205f20905b815481529060010190602001808311610a5657829003601f168201915b50505050509050919050565b610a87612a4f565b8060095f8481526020019081526020015f20819055505050565b610aa9612a4f565b8181600a5f8681526020019081526020015f209182610ac9929190614320565b50505050565b610ad7612ad6565b60016002811115610aeb57610aea613bca565b5b600e5f8481526020019081526020015f205f9054906101000a900460ff166002811115610b1b57610b1a613bca565b5b1480610b675750600280811115610b3557610b34613bca565b5b600e5f8481526020019081526020015f205f9054906101000a900460ff166002811115610b6557610b64613bca565b5b145b610ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9d90614437565b60405180910390fd5b600f5f8381526020019081526020015f205f9054906101000a900460ff1615610c04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bfb9061449f565b60405180910390fd5b600b5f8381526020019081526020015f205481600c5f8581526020019081526020015f2054610c3391906144ea565b1115610c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6b90614567565b60405180910390fd5b5f81600d5f8581526020019081526020015f2054610c929190614585565b905080341015610cd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cce90614610565b60405180910390fd5b610cf133848460405180602001604052805f815250612b25565b81600c5f8581526020019081526020015f205f828254610d1191906144ea565b92505081905550823373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb7484604051610d5f91906133e3565b60405180910390a350610d70612d65565b5050565b610d7c612a4f565b600f5f8381526020019081526020015f205f9054906101000a900460ff1615610dda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd19061449f565b60405180910390fd5b80600e5f8481526020019081526020015f205f6101000a81548160ff02191690836002811115610e0d57610e0c613bca565b5b02179055505050565b600d602052805f5260405f205f915090505481565b610e33612a4f565b600f5f8481526020019081526020015f205f9054906101000a900460ff1615610e91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e8890614678565b60405180910390fd5b5f5b82829050811015610f3c57600160105f8681526020019081526020015f205f858585818110610ec557610ec4614696565b5b9050602002016020810190610eda9190613eee565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508080610f34906146c3565b915050610e93565b50505050565b838390508686905014610f8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f8190614754565b60405180910390fd5b8773ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611045575060015f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b611084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107b906147bc565b60405180910390fd5b5f805f5b88889050811015611198578888828181106110a6576110a5614696565b5b9050602002013592508686828181106110c2576110c1614696565b5b905060200201359150815f808d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f82825461112591906147da565b92505081905550815f808c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f82825461118691906144ea565b92505081905550806001019050611088565b508873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516112139493929190614875565b60405180910390a45f8973ffffffffffffffffffffffffffffffffffffffff163b1461130c5763bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168973ffffffffffffffffffffffffffffffffffffffff1663bc197c81338d8c8c8c8c8c8c6040518963ffffffff1660e01b81526004016112a79897969594939291906148ea565b6020604051808303815f875af11580156112c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112e7919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461133d565b5f73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b61137c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611373906149df565b60405180910390fd5b50505050505050505050565b611390612ad6565b5f60028111156113a3576113a2613bca565b5b600e5f8581526020019081526020015f205f9054906101000a900460ff1660028111156113d3576113d2613bca565b5b148061141f57506002808111156113ed576113ec613bca565b5b600e5f8581526020019081526020015f205f9054906101000a900460ff16600281111561141d5761141c613bca565b5b145b61145e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145590614a47565b60405180910390fd5b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900460ff16156114f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ee90614aaf565b60405180910390fd5b600b5f8481526020019081526020015f2054600c5f8581526020019081526020015f20541061155b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155290614b17565b60405180910390fd5b5f3360405160200161156d9190614b7a565b6040516020818303038152906040528051906020012090506115e18383808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f8201169050808301925050505050505060095f8781526020019081526020015f205483612d6f565b611620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161790614bde565b60405180910390fd5b600160115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f6101000a81548160ff02191690831515021790555061169f3385600160405180602001604052805f815250612b25565b6001600c5f8681526020019081526020015f205f8282546116c091906144ea565b92505081905550833373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb74600160405161170f9190614c35565b60405180910390a350611720612d65565b505050565b6010602052815f5260405f20602052805f5260405f205f915091509054906101000a900460ff1681565b6060828290508585905014611799576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179090614754565b60405180910390fd5b8484905067ffffffffffffffff8111156117b6576117b5613c5a565b5b6040519080825280602002602001820160405280156117e45781602001602082028036833780820191505090505b5090505f5b858590508110156118aa575f8087878481811061180957611808614696565b5b905060200201602081019061181e9190613eee565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f85858481811061186b5761186a614696565b5b9050602002013581526020019081526020015f205482828151811061189357611892614696565b5b6020026020010181815250508060010190506117e9565b50949350505050565b600e602052805f5260405f205f915054906101000a900460ff1681565b6118d8612a4f565b80600890816118e79190614c4e565b5050565b5f600260149054906101000a900460ff16905090565b611909612a4f565b6119125f612d85565b565b6009602052805f5260405f205f915090505481565b60605f6008805461193990614149565b90501161197b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197290614d67565b60405180910390fd5b600861198683612e48565b604051602001611997929190614e89565b6040516020818303038152906040529050919050565b600b602052805f5260405f205f915090505481565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6119f2612a4f565b8060059081611a019190614c4e565b5050565b5f60115f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f9054906101000a900460ff1615611a6c575f9050611af6565b5f84604051602001611a7e9190614b7a565b604051602081830303815290604052805190602001209050611af28484808060200260200160405190810160405280939291908181526020018383602002808284375f81840152601f19601f8201169050808301925050505050505060095f8981526020019081526020015f205483612d6f565b9150505b949350505050565b606060078054611b0d90614149565b80601f0160208091040260200160405190810160405280929190818152602001828054611b3990614149565b8015611b845780601f10611b5b57610100808354040283529160200191611b84565b820191905f5260205f20905b815481529060010190602001808311611b6757829003601f168201915b5050505050905090565b600f602052805f5260405f205f915054906101000a900460ff1681565b611bb58282612f12565b5050565b6060805f611bc7600461300a565b90505f8167ffffffffffffffff811115611be457611be3613c5a565b5b604051908082528060200260200182016040528015611c125781602001602082028036833780820191505090505b5090505f8267ffffffffffffffff811115611c3057611c2f613c5a565b5b604051908082528060200260200182016040528015611c5e5781602001602082028036833780820191505090505b5090505f5b83811015611d17575f805f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205490505f811115611d035781848381518110611cd657611cd5614696565b5b60200260200101818152505080838381518110611cf657611cf5614696565b5b6020026020010181815250505b508080611d0f906146c3565b915050611c63565b50818194509450505050915091565b600c602052805f5260405f205f915090505481565b611d43612a4f565b611d4b612ad6565b5f4790505f8111611d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d8890614f01565b60405180910390fd5b611d996119c2565b73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611ddb573d5f803e3d5ffd5b5050611de5612d65565b565b611def612a4f565b600f5f8281526020019081526020015f205f9054906101000a900460ff1615611e4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4490614f69565b60405180910390fd5b6001600f5f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555050565b606060058054611e8890614149565b80601f0160208091040260200160405190810160405280929190818152602001828054611eb490614149565b8015611eff5780601f10611ed657610100808354040283529160200191611eff565b820191905f5260205f20905b815481529060010190602001808311611ee257829003601f168201915b5050505050905090565b6001602052815f5260405f20602052805f5260405f205f915091509054906101000a900460ff1681565b611f3b612ad6565b60105f8281526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16611fd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fca90614fd1565b60405180910390fd5b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f9054906101000a900460ff161561206c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206390615039565b60405180910390fd5b600b5f8281526020019081526020015f2054600c5f8381526020019081526020015f2054106120d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c790614b17565b60405180910390fd5b600160115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555061214f3382600160405180602001604052805f815250612b25565b6001600c5f8381526020019081526020015f205f82825461217091906144ea565b92505081905550803373ffffffffffffffffffffffffffffffffffffffff167f654aa85b2af57b53beb55f7fe31413e8d6d5ab5411a0c0c7fe975140f96abb7460016040516121bf9190614c35565b60405180910390a36121cf612d65565b50565b8573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061228d575060015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b6122cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c3906147bc565b60405180910390fd5b825f808873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f82825461232691906147da565b92505081905550825f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f82825461238791906144ea565b925050819055508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612404929190615057565b60405180910390a45f8573ffffffffffffffffffffffffffffffffffffffff163b146124f95763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168573ffffffffffffffffffffffffffffffffffffffff1663f23a6e613389888888886040518763ffffffff1660e01b81526004016124949695949392919061507e565b6020604051808303815f875af11580156124b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124d4919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461252a565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b612569576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612560906149df565b60405180910390fd5b505050505050565b612579612a4f565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036125e9575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016125e09190613dfc565b60405180910390fd5b6125f281612d85565b50565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806126b0575060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff165b6126ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e690615122565b60405180910390fd5b805f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2054101561277d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127749061518a565b60405180910390fd5b612788838383613016565b80600c5f8481526020019081526020015f205f8282546127a891906147da565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612825929190615057565b60405180910390a4505050565b61283a612a4f565b61284460046130fa565b5f61284f600461300a565b90505f8686905011612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d906151f2565b60405180910390fd5b868811156128d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128d090615280565b60405180910390fd5b8585600a5f8481526020019081526020015f2091826128f9929190614320565b508360095f8381526020019081526020015f208190555082600d5f8381526020019081526020015f208190555086600b5f8381526020019081526020015f208190555081600e5f8381526020019081526020015f205f6101000a81548160ff0219169083600281111561296f5761296e613bca565b5b02179055505f8811156129b45761299d6129876119c2565b828a60405180602001604052805f815250612b25565b87600c5f8381526020019081526020015f20819055505b5050505050505050565b5f6301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612a18575063d9b67a2660e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612a485750630e89341c60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b612a5761310e565b73ffffffffffffffffffffffffffffffffffffffff16612a756119c2565b73ffffffffffffffffffffffffffffffffffffffff1614612ad457612a9861310e565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612acb9190613dfc565b60405180910390fd5b565b600260035403612b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b12906152e8565b60405180910390fd5b6002600381905550565b815f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f828254612b7f91906144ea565b925050819055508373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628686604051612bfc929190615057565b60405180910390a45f8473ffffffffffffffffffffffffffffffffffffffff163b14612cef5763f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff1663f23a6e61335f8787876040518663ffffffff1660e01b8152600401612c8a959493929190615348565b6020604051808303815f875af1158015612ca6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cca919061496a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612d20565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614155b612d5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d56906149df565b60405180910390fd5b50505050565b6001600381905550565b5f82612d7b8584613115565b1490509392505050565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60605f6001612e5684613169565b0190505f8167ffffffffffffffff811115612e7457612e73613c5a565b5b6040519080825280601f01601f191660200182016040528015612ea65781602001600182028036833780820191505090505b5090505f82602001820190505b600115612f07578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612efc57612efb6153a0565b5b0494505f8503612eb3575b819350505050919050565b8060015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612ffe9190613496565b60405180910390a35050565b5f815f01549050919050565b805f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f82825461307091906147da565b925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516130ed929190615057565b60405180910390a4505050565b6001815f015f828254019250508190555050565b5f33905090565b5f808290505f5b845181101561315e576131498286838151811061313c5761313b614696565b5b60200260200101516132ba565b91508080613156906146c3565b91505061311c565b508091505092915050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106131c5577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816131bb576131ba6153a0565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613202576d04ee2d6d415b85acef810000000083816131f8576131f76153a0565b5b0492506020810190505b662386f26fc10000831061323157662386f26fc100008381613227576132266153a0565b5b0492506010810190505b6305f5e100831061325a576305f5e10083816132505761324f6153a0565b5b0492506008810190505b612710831061327f576127108381613275576132746153a0565b5b0492506004810190505b606483106132a25760648381613298576132976153a0565b5b0492506002810190505b600a83106132b1576001810190505b80915050919050565b5f8183106132d1576132cc82846132e4565b6132dc565b6132db83836132e4565b5b905092915050565b5f825f528160205260405f20905092915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61333282613309565b9050919050565b61334281613328565b811461334c575f80fd5b50565b5f8135905061335d81613339565b92915050565b5f819050919050565b61337581613363565b811461337f575f80fd5b50565b5f813590506133908161336c565b92915050565b5f80604083850312156133ac576133ab613301565b5b5f6133b98582860161334f565b92505060206133ca85828601613382565b9150509250929050565b6133dd81613363565b82525050565b5f6020820190506133f65f8301846133d4565b92915050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613430816133fc565b811461343a575f80fd5b50565b5f8135905061344b81613427565b92915050565b5f6020828403121561346657613465613301565b5b5f6134738482850161343d565b91505092915050565b5f8115159050919050565b6134908161347c565b82525050565b5f6020820190506134a95f830184613487565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156134e65780820151818401526020810190506134cb565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61350b826134af565b61351581856134b9565b93506135258185602086016134c9565b61352e816134f1565b840191505092915050565b5f6020820190508181035f8301526135518184613501565b905092915050565b5f6020828403121561356e5761356d613301565b5b5f61357b84828501613382565b91505092915050565b5f819050919050565b61359681613584565b81146135a0575f80fd5b50565b5f813590506135b18161358d565b92915050565b5f80604083850312156135cd576135cc613301565b5b5f6135da85828601613382565b92505060206135eb858286016135a3565b9150509250929050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112613616576136156135f5565b5b8235905067ffffffffffffffff811115613633576136326135f9565b5b60208301915083600182028301111561364f5761364e6135fd565b5b9250929050565b5f805f6040848603121561366d5761366c613301565b5b5f61367a86828701613382565b935050602084013567ffffffffffffffff81111561369b5761369a613305565b5b6136a786828701613601565b92509250509250925092565b5f80604083850312156136c9576136c8613301565b5b5f6136d685828601613382565b92505060206136e785828601613382565b9150509250929050565b600381106136fd575f80fd5b50565b5f8135905061370e816136f1565b92915050565b5f806040838503121561372a57613729613301565b5b5f61373785828601613382565b925050602061374885828601613700565b9150509250929050565b5f8083601f840112613767576137666135f5565b5b8235905067ffffffffffffffff811115613784576137836135f9565b5b6020830191508360208202830111156137a05761379f6135fd565b5b9250929050565b5f805f604084860312156137be576137bd613301565b5b5f6137cb86828701613382565b935050602084013567ffffffffffffffff8111156137ec576137eb613305565b5b6137f886828701613752565b92509250509250925092565b5f8083601f840112613819576138186135f5565b5b8235905067ffffffffffffffff811115613836576138356135f9565b5b602083019150836020820283011115613852576138516135fd565b5b9250929050565b5f8083601f84011261386e5761386d6135f5565b5b8235905067ffffffffffffffff81111561388b5761388a6135f9565b5b6020830191508360018202830111156138a7576138a66135fd565b5b9250929050565b5f805f805f805f8060a0898b0312156138ca576138c9613301565b5b5f6138d78b828c0161334f565b98505060206138e88b828c0161334f565b975050604089013567ffffffffffffffff81111561390957613908613305565b5b6139158b828c01613804565b9650965050606089013567ffffffffffffffff81111561393857613937613305565b5b6139448b828c01613804565b9450945050608089013567ffffffffffffffff81111561396757613966613305565b5b6139738b828c01613859565b92509250509295985092959890939650565b5f8083601f84011261399a576139996135f5565b5b8235905067ffffffffffffffff8111156139b7576139b66135f9565b5b6020830191508360208202830111156139d3576139d26135fd565b5b9250929050565b5f805f604084860312156139f1576139f0613301565b5b5f6139fe86828701613382565b935050602084013567ffffffffffffffff811115613a1f57613a1e613305565b5b613a2b86828701613985565b92509250509250925092565b5f8060408385031215613a4d57613a4c613301565b5b5f613a5a85828601613382565b9250506020613a6b8582860161334f565b9150509250929050565b5f805f8060408587031215613a8d57613a8c613301565b5b5f85013567ffffffffffffffff811115613aaa57613aa9613305565b5b613ab687828801613752565b9450945050602085013567ffffffffffffffff811115613ad957613ad8613305565b5b613ae587828801613804565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613b2581613363565b82525050565b5f613b368383613b1c565b60208301905092915050565b5f602082019050919050565b5f613b5882613af3565b613b628185613afd565b9350613b6d83613b0d565b805f5b83811015613b9d578151613b848882613b2b565b9750613b8f83613b42565b925050600181019050613b70565b5085935050505092915050565b5f6020820190508181035f830152613bc28184613b4e565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613c0857613c07613bca565b5b50565b5f819050613c1882613bf7565b919050565b5f613c2782613c0b565b9050919050565b613c3781613c1d565b82525050565b5f602082019050613c505f830184613c2e565b92915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613c90826134f1565b810181811067ffffffffffffffff82111715613caf57613cae613c5a565b5b80604052505050565b5f613cc16132f8565b9050613ccd8282613c87565b919050565b5f67ffffffffffffffff821115613cec57613ceb613c5a565b5b613cf5826134f1565b9050602081019050919050565b828183375f83830152505050565b5f613d22613d1d84613cd2565b613cb8565b905082815260208101848484011115613d3e57613d3d613c56565b5b613d49848285613d02565b509392505050565b5f82601f830112613d6557613d646135f5565b5b8135613d75848260208601613d10565b91505092915050565b5f60208284031215613d9357613d92613301565b5b5f82013567ffffffffffffffff811115613db057613daf613305565b5b613dbc84828501613d51565b91505092915050565b613dce81613584565b82525050565b5f602082019050613de75f830184613dc5565b92915050565b613df681613328565b82525050565b5f602082019050613e0f5f830184613ded565b92915050565b5f805f8060608587031215613e2d57613e2c613301565b5b5f613e3a87828801613382565b9450506020613e4b8782880161334f565b935050604085013567ffffffffffffffff811115613e6c57613e6b613305565b5b613e7887828801613985565b925092505092959194509250565b613e8f8161347c565b8114613e99575f80fd5b50565b5f81359050613eaa81613e86565b92915050565b5f8060408385031215613ec657613ec5613301565b5b5f613ed38582860161334f565b9250506020613ee485828601613e9c565b9150509250929050565b5f60208284031215613f0357613f02613301565b5b5f613f108482850161334f565b91505092915050565b5f6040820190508181035f830152613f318185613b4e565b90508181036020830152613f458184613b4e565b90509392505050565b5f8060408385031215613f6457613f63613301565b5b5f613f718582860161334f565b9250506020613f828582860161334f565b9150509250929050565b5f805f805f8060a08789031215613fa657613fa5613301565b5b5f613fb389828a0161334f565b9650506020613fc489828a0161334f565b9550506040613fd589828a01613382565b9450506060613fe689828a01613382565b935050608087013567ffffffffffffffff81111561400757614006613305565b5b61401389828a01613859565b92509250509295509295509295565b5f805f6060848603121561403957614038613301565b5b5f6140468682870161334f565b935050602061405786828701613382565b925050604061406886828701613382565b9150509250925092565b5f805f805f805f60c0888a03121561408d5761408c613301565b5b5f61409a8a828b01613382565b97505060206140ab8a828b01613382565b965050604088013567ffffffffffffffff8111156140cc576140cb613305565b5b6140d88a828b01613601565b955095505060606140eb8a828b016135a3565b93505060806140fc8a828b01613382565b92505060a061410d8a828b01613700565b91505092959891949750929550565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061416057607f821691505b6020821081036141735761417261411c565b5b50919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026141df7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826141a4565b6141e986836141a4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61422461421f61421a84613363565b614201565b613363565b9050919050565b5f819050919050565b61423d8361420a565b6142516142498261422b565b8484546141b0565b825550505050565b5f90565b614265614259565b614270818484614234565b505050565b5b81811015614293576142885f8261425d565b600181019050614276565b5050565b601f8211156142d8576142a981614183565b6142b284614195565b810160208510156142c1578190505b6142d56142cd85614195565b830182614275565b50505b505050565b5f82821c905092915050565b5f6142f85f19846008026142dd565b1980831691505092915050565b5f61431083836142e9565b9150826002028217905092915050565b61432a8383614179565b67ffffffffffffffff81111561434357614342613c5a565b5b61434d8254614149565b614358828285614297565b5f601f831160018114614385575f8415614373578287013590505b61437d8582614305565b8655506143e4565b601f19841661439386614183565b5f5b828110156143ba57848901358255600182019150602085019450602081019050614395565b868310156143d757848901356143d3601f8916826142e9565b8355505b6001600288020188555050505b50505050505050565b7f546f6b656e206e6f7420617661696c61626c6520666f72206d696e74696e67005f82015250565b5f614421601f836134b9565b915061442c826143ed565b602082019050919050565b5f6020820190508181035f83015261444e81614415565b9050919050565b7f546f6b656e2069732066726f7a656e00000000000000000000000000000000005f82015250565b5f614489600f836134b9565b915061449482614455565b602082019050919050565b5f6020820190508181035f8301526144b68161447d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6144f482613363565b91506144ff83613363565b9250828201905080821115614517576145166144bd565b5b92915050565b7f45786365656473206d617820737570706c7900000000000000000000000000005f82015250565b5f6145516012836134b9565b915061455c8261451d565b602082019050919050565b5f6020820190508181035f83015261457e81614545565b9050919050565b5f61458f82613363565b915061459a83613363565b92508282026145a881613363565b915082820484148315176145bf576145be6144bd565b5b5092915050565b7f496e73756666696369656e7420666565000000000000000000000000000000005f82015250565b5f6145fa6010836134b9565b9150614605826145c6565b602082019050919050565b5f6020820190508181035f830152614627816145ee565b9050919050565b7f546f6b656e2066726f7a656e00000000000000000000000000000000000000005f82015250565b5f614662600c836134b9565b915061466d8261462e565b602082019050919050565b5f6020820190508181035f83015261468f81614656565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6146cd82613363565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036146ff576146fe6144bd565b5b600182019050919050565b7f4c454e4754485f4d49534d4154434800000000000000000000000000000000005f82015250565b5f61473e600f836134b9565b91506147498261470a565b602082019050919050565b5f6020820190508181035f83015261476b81614732565b9050919050565b7f4e4f545f415554484f52495a45440000000000000000000000000000000000005f82015250565b5f6147a6600e836134b9565b91506147b182614772565b602082019050919050565b5f6020820190508181035f8301526147d38161479a565b9050919050565b5f6147e482613363565b91506147ef83613363565b9250828203905081811115614807576148066144bd565b5b92915050565b5f80fd5b82818337505050565b5f6148258385613afd565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156148585761485761480d565b5b602083029250614869838584614811565b82840190509392505050565b5f6040820190508181035f83015261488e81868861481a565b905081810360208301526148a381848661481a565b905095945050505050565b5f82825260208201905092915050565b5f6148c983856148ae565b93506148d6838584613d02565b6148df836134f1565b840190509392505050565b5f60a0820190506148fd5f83018b613ded565b61490a602083018a613ded565b818103604083015261491d81888a61481a565b9050818103606083015261493281868861481a565b905081810360808301526149478184866148be565b90509998505050505050505050565b5f8151905061496481613427565b92915050565b5f6020828403121561497f5761497e613301565b5b5f61498c84828501614956565b91505092915050565b7f554e534146455f524543495049454e54000000000000000000000000000000005f82015250565b5f6149c96010836134b9565b91506149d482614995565b602082019050919050565b5f6020820190508181035f8301526149f6816149bd565b9050919050565b7f546f6b656e206e6f7420617661696c61626c6520666f7220636c61696d696e675f82015250565b5f614a316020836134b9565b9150614a3c826149fd565b602082019050919050565b5f6020820190508181035f830152614a5e81614a25565b9050919050565b7f4e465420616c726561647920636c61696d6564000000000000000000000000005f82015250565b5f614a996013836134b9565b9150614aa482614a65565b602082019050919050565b5f6020820190508181035f830152614ac681614a8d565b9050919050565b7f4d617820737570706c79207265616368656400000000000000000000000000005f82015250565b5f614b016012836134b9565b9150614b0c82614acd565b602082019050919050565b5f6020820190508181035f830152614b2e81614af5565b9050919050565b5f8160601b9050919050565b5f614b4b82614b35565b9050919050565b5f614b5c82614b41565b9050919050565b614b74614b6f82613328565b614b52565b82525050565b5f614b858284614b63565b60148201915081905092915050565b7f496e76616c69642070726f6f66000000000000000000000000000000000000005f82015250565b5f614bc8600d836134b9565b9150614bd382614b94565b602082019050919050565b5f6020820190508181035f830152614bf581614bbc565b9050919050565b5f819050919050565b5f614c1f614c1a614c1584614bfc565b614201565b613363565b9050919050565b614c2f81614c05565b82525050565b5f602082019050614c485f830184614c26565b92915050565b614c57826134af565b67ffffffffffffffff811115614c7057614c6f613c5a565b5b614c7a8254614149565b614c85828285614297565b5f60209050601f831160018114614cb6575f8415614ca4578287015190505b614cae8582614305565b865550614d15565b601f198416614cc486614183565b5f5b82811015614ceb57848901518255600182019150602085019450602081019050614cc6565b86831015614d085784890151614d04601f8916826142e9565b8355505b6001600288020188555050505b505050505050565b7f62617365555249206e6f742073657400000000000000000000000000000000005f82015250565b5f614d51600f836134b9565b9150614d5c82614d1d565b602082019050919050565b5f6020820190508181035f830152614d7e81614d45565b9050919050565b5f81905092915050565b5f8154614d9b81614149565b614da58186614d85565b9450600182165f8114614dbf5760018114614dd457614e06565b60ff1983168652811515820286019350614e06565b614ddd85614183565b5f5b83811015614dfe57815481890152600182019150602081019050614ddf565b838801955050505b50505092915050565b5f614e19826134af565b614e238185614d85565b9350614e338185602086016134c9565b80840191505092915050565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000005f82015250565b5f614e73600583614d85565b9150614e7e82614e3f565b600582019050919050565b5f614e948285614d8f565b9150614ea08284614e0f565b9150614eab82614e67565b91508190509392505050565b7f4e6f2045544820746f20776974686472617700000000000000000000000000005f82015250565b5f614eeb6012836134b9565b9150614ef682614eb7565b602082019050919050565b5f6020820190508181035f830152614f1881614edf565b9050919050565b7f494420616c72656164792066726f7a656e0000000000000000000000000000005f82015250565b5f614f536011836134b9565b9150614f5e82614f1f565b602082019050919050565b5f6020820190508181035f830152614f8081614f47565b9050919050565b7f4e6f742077686974656c697374656400000000000000000000000000000000005f82015250565b5f614fbb600f836134b9565b9150614fc682614f87565b602082019050919050565b5f6020820190508181035f830152614fe881614faf565b9050919050565b7f416c726561647920636c61696d656400000000000000000000000000000000005f82015250565b5f615023600f836134b9565b915061502e82614fef565b602082019050919050565b5f6020820190508181035f83015261505081615017565b9050919050565b5f60408201905061506a5f8301856133d4565b61507760208301846133d4565b9392505050565b5f60a0820190506150915f830189613ded565b61509e6020830188613ded565b6150ab60408301876133d4565b6150b860608301866133d4565b81810360808301526150cb8184866148be565b9050979650505050505050565b7f43616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665645f82015250565b5f61510c6020836134b9565b9150615117826150d8565b602082019050919050565b5f6020820190508181035f83015261513981615100565b9050919050565b7f4275726e20616d6f756e7420657863656564732062616c616e636500000000005f82015250565b5f615174601b836134b9565b915061517f82615140565b602082019050919050565b5f6020820190508181035f8301526151a181615168565b9050919050565b7f555249206d7573742062652073657400000000000000000000000000000000005f82015250565b5f6151dc600f836134b9565b91506151e7826151a8565b602082019050919050565b5f6020820190508181035f830152615209816151d0565b9050919050565b7f496e697469616c20616d6f756e742063616e6e6f7420657863656564206d61785f8201527f20737570706c7900000000000000000000000000000000000000000000000000602082015250565b5f61526a6027836134b9565b915061527582615210565b604082019050919050565b5f6020820190508181035f8301526152978161525e565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c005f82015250565b5f6152d2601f836134b9565b91506152dd8261529e565b602082019050919050565b5f6020820190508181035f8301526152ff816152c6565b9050919050565b5f81519050919050565b5f61531a82615306565b61532481856148ae565b93506153348185602086016134c9565b61533d816134f1565b840191505092915050565b5f60a08201905061535b5f830188613ded565b6153686020830187613ded565b61537560408301866133d4565b61538260608301856133d4565b81810360808301526153948184615310565b90509695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffdfea26469706673582212203308cc927bb7d837b8b0def943e234ae7a0ada6206ea1b60272533c1de09fe4c64736f6c63430008140033

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

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000006942013379d195323e17cd2616435dce819c1fa9000000000000000000000000000000000000000000000000000000000000001050657065636f696e2078204672656e7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f50455045434f494e434f4c4c4142530000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Pepecoin x Frens
Arg [1] : symbol_ (string): PEPECOINCOLLABS
Arg [2] : initialOwner (address): 0x6942013379d195323E17CD2616435DcE819c1fA9

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000006942013379d195323e17cd2616435dce819c1fa9
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [4] : 50657065636f696e2078204672656e7300000000000000000000000000000000
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [6] : 50455045434f494e434f4c4c4142530000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.