Address Details
contract

0xB8e38D2b8f8F4Fa075D903009aa80b1B99193196

Contract Name
gameItems
Creator
0x3e89ab–96ea29 at 0x583ce6–a62928
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
17603852
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
gameItems




Optimization enabled
false
Compiler version
v0.8.18+commit.87f61d96




EVM Version
paris




Verified at
2023-05-06T16:28:39.943095Z

thirdweb.sol

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { ERC1155Base } from "@thirdweb-dev/contracts/base/ERC1155Base.sol";

contract gameItems{

    ERC1155Base baseContract;
    address public custodian;
    address public newCustodian;

    event custodyTransferInitiated (address currentCustodian, address newCustodian);
    event custodyTransferCompleted (address custodian);

    constructor (
        string memory _name,
        string memory _symbol,
        address _royaltyRecipient,
        uint128 _royaltyBps
        ) {
        baseContract = new ERC1155Base(_name, _symbol, _royaltyRecipient, _royaltyBps);
        baseContract.setOperatorRestriction(false); // the OperatorFilterToggle contract handles the emit operation here
        baseContract.setOwner(address(this)); // Ownable contract handles the emit as well
        custodian = msg.sender;

        //call the first mint so mintTo can work later on
        baseContract.mintTo(custodian, type(uint).max, "ECSTASY ARMOR X1.0.0", 1);
    }

    modifier onlyCustodian() {
        require(msg.sender == custodian, "ERR: NOT CUSTODIAN");
        _;
    }

    //Custodian change
    function intiateCustodyTransfer(address _newCustodian) external onlyCustodian{
        require(_newCustodian != address(0), "ERR: ZERO ADDRESS");
        newCustodian = _newCustodian;
        emit custodyTransferInitiated(custodian, newCustodian);
    }

    function acceptCustody() external {
        require(msg.sender == newCustodian, "ERR: NOT NEW CUSTODIAN");
        custodian = newCustodian;
        newCustodian = address(0);
        emit custodyTransferCompleted(custodian);
    }
    
    //Returns the owner of the base contract
    function getOwner() external view returns(address) {
        return baseContract.owner();
    }

    function reward(address to, bool newCollection, uint tokenId, string memory uri, uint amount) external onlyCustodian {
        require(bytes(uri).length > 0, "ERR: EMPTY STRING!");
        if(newCollection){
            baseContract.mintTo(to, type(uint256).max, uri, amount);
        }else{
            baseContract.mintTo(to, tokenId, uri, amount);
        }
    }

    function balanceOf (address _address, uint _id) external view returns (uint) {
        return baseContract.balanceOf(_address, _id);
    }

    function batchBalanceOf (address[] calldata _address, uint[] calldata _id) external view returns (uint[] memory) {
        return baseContract.balanceOfBatch(_address, _id);
    }

    //Royalty details

    function setRoyaltyInfo(uint tokenId, address royaltyRecipient, uint royaltyBps) external onlyCustodian{
        baseContract.setRoyaltyInfoForToken(tokenId, royaltyRecipient, royaltyBps);
        // add an emit statement here
    }

    function getRoyaltyInfo(uint tokenId) external view returns (address, uint) {
        return baseContract.getRoyaltyInfoForToken(tokenId);
    }

    function calculateRoyalty (uint tokenId, uint salePrice) external view returns (uint) {
        ( , uint royaltyValue) = baseContract.royaltyInfo(tokenId, salePrice);
        return royaltyValue;
    }

    //MetaData

    function getName() external view returns (string memory) {
        return baseContract.name();
    }

    function getSymbol() external view returns (string memory) {
        return baseContract.symbol();
    }

    function getURI(uint tokenId) external view returns (string memory){
        return baseContract.uri(tokenId);
    }

    function totalSupply(uint tokenId) external view returns (uint) {
        return baseContract.totalSupply(tokenId);
    }
}
        

/_thirdweb-dev/contracts/base/ERC1155Base.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import { ERC1155 } from "../eip/ERC1155.sol";

import "../extension/ContractMetadata.sol";
import "../extension/Multicall.sol";
import "../extension/Ownable.sol";
import "../extension/Royalty.sol";
import "../extension/BatchMintMetadata.sol";
import "../extension/DefaultOperatorFilterer.sol";

import "../lib/TWStrings.sol";

/**
 *  The `ERC1155Base` smart contract implements the ERC1155 NFT standard.
 *  It includes the following additions to standard ERC1155 logic:
 *
 *      - Ability to mint NFTs via the provided `mintTo` and `batchMintTo` functions.
 *
 *      - Contract metadata for royalty support on platforms such as OpenSea that use
 *        off-chain information to distribute roaylties.
 *
 *      - Ownership of the contract, with the ability to restrict certain functions to
 *        only be called by the contract's owner.
 *
 *      - Multicall capability to perform multiple actions atomically
 *
 *      - EIP 2981 compliance for royalty support on NFT marketplaces.
 */

contract ERC1155Base is
    ERC1155,
    ContractMetadata,
    Ownable,
    Royalty,
    Multicall,
    BatchMintMetadata,
    DefaultOperatorFilterer
{
    using TWStrings for uint256;

    /*//////////////////////////////////////////////////////////////
                        State variables
    //////////////////////////////////////////////////////////////*/

    /// @dev The tokenId of the next NFT to mint.
    uint256 internal nextTokenIdToMint_;

    /*//////////////////////////////////////////////////////////////
                        Mappings
    //////////////////////////////////////////////////////////////*/

    /**
     *  @notice Returns the total supply of NFTs of a given tokenId
     *  @dev Mapping from tokenId => total circulating supply of NFTs of that tokenId.
     */
    mapping(uint256 => uint256) public totalSupply;

    /*//////////////////////////////////////////////////////////////
                            Constructor
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        address _royaltyRecipient,
        uint128 _royaltyBps
    ) ERC1155(_name, _symbol) {
        _setupOwner(msg.sender);
        _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps);
        _setOperatorRestriction(true);
    }

    /*//////////////////////////////////////////////////////////////
                    Overriden metadata logic
    //////////////////////////////////////////////////////////////*/

    /// @notice Returns the metadata URI for the given tokenId.
    function uri(uint256 _tokenId) public view virtual override returns (string memory) {
        string memory uriForToken = _uri[_tokenId];
        if (bytes(uriForToken).length > 0) {
            return uriForToken;
        }

        string memory batchUri = _getBaseURI(_tokenId);
        return string(abi.encodePacked(batchUri, _tokenId.toString()));
    }

    /*//////////////////////////////////////////////////////////////
                        Mint / burn logic
    //////////////////////////////////////////////////////////////*/

    /**
     *  @notice          Lets an authorized address mint NFTs to a recipient.
     *  @dev             - The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs.
     *                   - If `_tokenId == type(uint256).max` a new NFT at tokenId `nextTokenIdToMint` is minted. If the given
     *                     `tokenId < nextTokenIdToMint`, then additional supply of an existing NFT is being minted.
     *
     *  @param _to       The recipient of the NFTs to mint.
     *  @param _tokenId  The tokenId of the NFT to mint.
     *  @param _tokenURI The full metadata URI for the NFTs minted (if a new NFT is being minted).
     *  @param _amount   The amount of the same NFT to mint.
     */
    function mintTo(
        address _to,
        uint256 _tokenId,
        string memory _tokenURI,
        uint256 _amount
    ) public virtual {
        require(_canMint(), "Not authorized to mint.");

        uint256 tokenIdToMint;
        uint256 nextIdToMint = nextTokenIdToMint();

        if (_tokenId == type(uint256).max) {
            tokenIdToMint = nextIdToMint;
            nextTokenIdToMint_ += 1;
            _setTokenURI(nextIdToMint, _tokenURI);
        } else {
            require(_tokenId < nextIdToMint, "invalid id");
            tokenIdToMint = _tokenId;
        }

        _mint(_to, tokenIdToMint, _amount, "");
    }

    /**
     *  @notice          Lets an authorized address mint multiple NEW NFTs at once to a recipient.
     *  @dev             The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs.
     *                   If `_tokenIds[i] == type(uint256).max` a new NFT at tokenId `nextTokenIdToMint` is minted. If the given
     *                   `tokenIds[i] < nextTokenIdToMint`, then additional supply of an existing NFT is minted.
     *                   The metadata for each new NFT is stored at `baseURI/{tokenID of NFT}`
     *
     *  @param _to       The recipient of the NFT to mint.
     *  @param _tokenIds The tokenIds of the NFTs to mint.
     *  @param _amounts  The amounts of each NFT to mint.
     *  @param _baseURI  The baseURI for the `n` number of NFTs minted. The metadata for each NFT is `baseURI/tokenId`
     */
    function batchMintTo(
        address _to,
        uint256[] memory _tokenIds,
        uint256[] memory _amounts,
        string memory _baseURI
    ) public virtual {
        require(_canMint(), "Not authorized to mint.");
        require(_amounts.length > 0, "Minting zero tokens.");
        require(_tokenIds.length == _amounts.length, "Length mismatch.");

        uint256 nextIdToMint = nextTokenIdToMint();
        uint256 startNextIdToMint = nextIdToMint;

        uint256 numOfNewNFTs;

        for (uint256 i = 0; i < _tokenIds.length; i += 1) {
            if (_tokenIds[i] == type(uint256).max) {
                _tokenIds[i] = nextIdToMint;

                nextIdToMint += 1;
                numOfNewNFTs += 1;
            } else {
                require(_tokenIds[i] < nextIdToMint, "invalid id");
            }
        }

        if (numOfNewNFTs > 0) {
            _batchMintMetadata(startNextIdToMint, numOfNewNFTs, _baseURI);
        }

        nextTokenIdToMint_ = nextIdToMint;
        _mintBatch(_to, _tokenIds, _amounts, "");
    }

    /**
     *  @notice         Lets an owner or approved operator burn NFTs of the given tokenId.
     *
     *  @param _owner   The owner of the NFT to burn.
     *  @param _tokenId The tokenId of the NFT to burn.
     *  @param _amount  The amount of the NFT to burn.
     */
    function burn(
        address _owner,
        uint256 _tokenId,
        uint256 _amount
    ) external virtual {
        address caller = msg.sender;

        require(caller == _owner || isApprovedForAll[_owner][caller], "Unapproved caller");
        require(balanceOf[_owner][_tokenId] >= _amount, "Not enough tokens owned");

        _burn(_owner, _tokenId, _amount);
    }

    /**
     *  @notice         Lets an owner or approved operator burn NFTs of the given tokenIds.
     *
     *  @param _owner    The owner of the NFTs to burn.
     *  @param _tokenIds The tokenIds of the NFTs to burn.
     *  @param _amounts  The amounts of the NFTs to burn.
     */
    function burnBatch(
        address _owner,
        uint256[] memory _tokenIds,
        uint256[] memory _amounts
    ) external virtual {
        address caller = msg.sender;

        require(caller == _owner || isApprovedForAll[_owner][caller], "Unapproved caller");
        require(_tokenIds.length == _amounts.length, "Length mismatch");

        for (uint256 i = 0; i < _tokenIds.length; i += 1) {
            require(balanceOf[_owner][_tokenIds[i]] >= _amounts[i], "Not enough tokens owned");
        }

        _burnBatch(_owner, _tokenIds, _amounts);
    }

    /*//////////////////////////////////////////////////////////////
                            ERC165 Logic
    //////////////////////////////////////////////////////////////*/

    /// @notice Returns whether this contract supports the given interface.
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155, IERC165) returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c || // ERC165 Interface ID for ERC1155MetadataURI
            interfaceId == type(IERC2981).interfaceId; // ERC165 ID for ERC2981
    }

    /*//////////////////////////////////////////////////////////////
                            View functions
    //////////////////////////////////////////////////////////////*/

    /// @notice The tokenId assigned to the next new NFT to be minted.
    function nextTokenIdToMint() public view virtual returns (uint256) {
        return nextTokenIdToMint_;
    }

    /*//////////////////////////////////////////////////////////////
                        ERC-1155 overrides
    //////////////////////////////////////////////////////////////*/

    /// @dev See {ERC1155-setApprovalForAll}
    function setApprovalForAll(address operator, bool approved)
        public
        virtual
        override(ERC1155)
        onlyAllowedOperatorApproval(operator)
    {
        super.setApprovalForAll(operator, approved);
    }

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override(ERC1155) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, id, amount, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual override(ERC1155) onlyAllowedOperator(from) {
        super.safeBatchTransferFrom(from, to, ids, amounts, data);
    }

    /*//////////////////////////////////////////////////////////////
                    Internal (overrideable) functions
    //////////////////////////////////////////////////////////////*/

    /// @dev Returns whether contract metadata can be set in the given execution context.
    function _canSetContractURI() internal view virtual override returns (bool) {
        return msg.sender == owner();
    }

    /// @dev Returns whether a token can be minted in the given execution context.
    function _canMint() internal view virtual returns (bool) {
        return msg.sender == owner();
    }

    /// @dev Returns whether owner can be set in the given execution context.
    function _canSetOwner() internal view virtual override returns (bool) {
        return msg.sender == owner();
    }

    /// @dev Returns whether royalty info can be set in the given execution context.
    function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
        return msg.sender == owner();
    }

    /// @dev Returns whether operator restriction can be set in the given execution context.
    function _canSetOperatorRestriction() internal virtual override returns (bool) {
        return msg.sender == owner();
    }

    /// @dev Runs before every token transfer / mint / burn.
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);

        if (from == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                totalSupply[ids[i]] += amounts[i];
            }
        }

        if (to == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                totalSupply[ids[i]] -= amounts[i];
            }
        }
    }
}
          

/_thirdweb-dev/contracts/eip/ERC1155.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

import "./interface/IERC1155.sol";
import "./interface/IERC1155Metadata.sol";
import "./interface/IERC1155Receiver.sol";

contract ERC1155 is IERC1155, IERC1155Metadata {
    /*//////////////////////////////////////////////////////////////
                        State variables
    //////////////////////////////////////////////////////////////*/

    string public name;
    string public symbol;

    /*//////////////////////////////////////////////////////////////
                            Mappings
    //////////////////////////////////////////////////////////////*/

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

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

    mapping(uint256 => string) internal _uri;

    /*//////////////////////////////////////////////////////////////
                            Constructor
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                            View functions
    //////////////////////////////////////////////////////////////*/

    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
    }

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

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

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf[accounts[i]][ids[i]];
        }

        return batchBalances;
    }

    /*//////////////////////////////////////////////////////////////
                            ERC1155 logic
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual override {
        address owner = msg.sender;
        require(owner != operator, "APPROVING_SELF");
        isApprovedForAll[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        require(from == msg.sender || isApprovedForAll[from][msg.sender], "!OWNER_OR_APPROVED");
        _safeTransferFrom(from, to, id, amount, data);
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public virtual override {
        require(from == msg.sender || isApprovedForAll[from][msg.sender], "!OWNER_OR_APPROVED");
        _safeBatchTransferFrom(from, to, ids, amounts, data);
    }

    /*//////////////////////////////////////////////////////////////
                            Internal logic
    //////////////////////////////////////////////////////////////*/

    function _safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "TO_ZERO_ADDR");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);

        uint256 fromBalance = balanceOf[from][id];
        require(fromBalance >= amount, "INSUFFICIENT_BAL");
        unchecked {
            balanceOf[from][id] = fromBalance - amount;
        }
        balanceOf[to][id] += amount;

        emit TransferSingle(operator, from, to, id, amount);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    function _safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");
        require(to != address(0), "TO_ZERO_ADDR");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

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

            uint256 fromBalance = balanceOf[from][id];
            require(fromBalance >= amount, "INSUFFICIENT_BAL");
            unchecked {
                balanceOf[from][id] = fromBalance - amount;
            }
            balanceOf[to][id] += amount;
        }

        emit TransferBatch(operator, from, to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    function _setTokenURI(uint256 tokenId, string memory newuri) internal virtual {
        _uri[tokenId] = newuri;
    }

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "TO_ZERO_ADDR");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data);

        balanceOf[to][id] += amount;
        emit TransferSingle(operator, address(0), to, id, amount);

        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
    }

    function _mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        require(to != address(0), "TO_ZERO_ADDR");
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

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

        emit TransferBatch(operator, address(0), to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "FROM_ZERO_ADDR");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

        uint256 fromBalance = balanceOf[from][id];
        require(fromBalance >= amount, "INSUFFICIENT_BAL");
        unchecked {
            balanceOf[from][id] = fromBalance - amount;
        }

        emit TransferSingle(operator, from, address(0), id, amount);
    }

    function _burnBatch(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        require(from != address(0), "FROM_ZERO_ADDR");
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        address operator = msg.sender;

        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

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

            uint256 fromBalance = balanceOf[from][id];
            require(fromBalance >= amount, "INSUFFICIENT_BAL");
            unchecked {
                balanceOf[from][id] = fromBalance - amount;
            }
        }

        emit TransferBatch(operator, from, address(0), ids, amounts);
    }

    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {}

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) private {
        if (to.code.length > 0) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                if (response != IERC1155Receiver.onERC1155Received.selector) {
                    revert("TOKENS_REJECTED");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("!ERC1155RECEIVER");
            }
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) private {
        if (to.code.length > 0) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
                bytes4 response
            ) {
                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
                    revert("TOKENS_REJECTED");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("!ERC1155RECEIVER");
            }
        }
    }

    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](1);
        array[0] = element;

        return array;
    }
}
          

/_thirdweb-dev/contracts/eip/interface/IERC1155.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/**
    @title ERC-1155 Multi Token Standard
    @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
    Note: The ERC-165 identifier for this interface is 0xd9b67a26.
 */
interface IERC1155 {
    /**
        @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
        The `_operator` argument MUST be msg.sender.
        The `_from` argument MUST be the address of the holder whose balance is decreased.
        The `_to` argument MUST be the address of the recipient whose balance is increased.
        The `_id` argument MUST be the token type being transferred.
        The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
        When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
        When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
    */
    event TransferSingle(
        address indexed _operator,
        address indexed _from,
        address indexed _to,
        uint256 _id,
        uint256 _value
    );

    /**
        @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
        The `_operator` argument MUST be msg.sender.
        The `_from` argument MUST be the address of the holder whose balance is decreased.
        The `_to` argument MUST be the address of the recipient whose balance is increased.
        The `_ids` argument MUST be the list of tokens being transferred.
        The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
        When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
        When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
    */
    event TransferBatch(
        address indexed _operator,
        address indexed _from,
        address indexed _to,
        uint256[] _ids,
        uint256[] _values
    );

    /**
        @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absense of an event assumes disabled).
    */
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /**
        @dev MUST emit when the URI is updated for a token ID.
        URIs are defined in RFC 3986.
        The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
    */
    event URI(string _value, uint256 indexed _id);

    /**
        @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
        MUST revert if `_to` is the zero address.
        MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
        MUST revert on any other error.
        MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
        After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
        @param _from    Source address
        @param _to      Target address
        @param _id      ID of the token type
        @param _value   Transfer amount
        @param _data    Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
    */
    function safeTransferFrom(
        address _from,
        address _to,
        uint256 _id,
        uint256 _value,
        bytes calldata _data
    ) external;

    /**
        @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
        MUST revert if `_to` is the zero address.
        MUST revert if length of `_ids` is not the same as length of `_values`.
        MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
        MUST revert on any other error.
        MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
        Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
        After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
        @param _from    Source address
        @param _to      Target address
        @param _ids     IDs of each token type (order and length must match _values array)
        @param _values  Transfer amounts per token type (order and length must match _ids array)
        @param _data    Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
    */
    function safeBatchTransferFrom(
        address _from,
        address _to,
        uint256[] calldata _ids,
        uint256[] calldata _values,
        bytes calldata _data
    ) external;

    /**
        @notice Get the balance of an account's Tokens.
        @param _owner  The address of the token holder
        @param _id     ID of the Token
        @return        The _owner's balance of the Token type requested
     */
    function balanceOf(address _owner, uint256 _id) external view returns (uint256);

    /**
        @notice Get the balance of multiple account/token pairs
        @param _owners The addresses of the token holders
        @param _ids    ID of the Tokens
        @return        The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair)
     */
    function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids)
        external
        view
        returns (uint256[] memory);

    /**
        @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
        @dev MUST emit the ApprovalForAll event on success.
        @param _operator  Address to add to the set of authorized operators
        @param _approved  True if the operator is approved, false to revoke approval
    */
    function setApprovalForAll(address _operator, bool _approved) external;

    /**
        @notice Queries the approval status of an operator for a given owner.
        @param _owner     The owner of the Tokens
        @param _operator  Address of authorized operator
        @return           True if the operator is approved, false if not
    */
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
          

/_thirdweb-dev/contracts/eip/interface/IERC1155Metadata.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/**
    Note: The ERC-165 identifier for this interface is 0x0e89341c.
*/
interface IERC1155Metadata {
    /**
        @notice A distinct Uniform Resource Identifier (URI) for a given token.
        @dev URIs are defined in RFC 3986.
        The URI may point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
        @return URI string
    */
    function uri(uint256 _id) external view returns (string memory);
}
          

/_thirdweb-dev/contracts/eip/interface/IERC1155Receiver.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}
          

/_thirdweb-dev/contracts/eip/interface/IERC165.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * [EIP](https://eips.ethereum.org/EIPS/eip-165).
 *
 * 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
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
          

/_thirdweb-dev/contracts/eip/interface/IERC2981.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be payed in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}
          

/_thirdweb-dev/contracts/extension/BatchMintMetadata.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  @title   Batch-mint Metadata
 *  @notice  The `BatchMintMetadata` is a contract extension for any base NFT contract. It lets the smart contract
 *           using this extension set metadata for `n` number of NFTs all at once. This is enabled by storing a single
 *           base URI for a batch of `n` NFTs, where the metadata for each NFT in a relevant batch is `baseURI/tokenId`.
 */

contract BatchMintMetadata {
    /// @dev Largest tokenId of each batch of tokens with the same baseURI.
    uint256[] private batchIds;

    /// @dev Mapping from id of a batch of tokens => to base URI for the respective batch of tokens.
    mapping(uint256 => string) private baseURI;

    /**
     *  @notice         Returns the count of batches of NFTs.
     *  @dev            Each batch of tokens has an in ID and an associated `baseURI`.
     *                  See {batchIds}.
     */
    function getBaseURICount() public view returns (uint256) {
        return batchIds.length;
    }

    /**
     *  @notice         Returns the ID for the batch of tokens the given tokenId belongs to.
     *  @dev            See {getBaseURICount}.
     *  @param _index   ID of a token.
     */
    function getBatchIdAtIndex(uint256 _index) public view returns (uint256) {
        if (_index >= getBaseURICount()) {
            revert("Invalid index");
        }
        return batchIds[_index];
    }

    /// @dev Returns the id for the batch of tokens the given tokenId belongs to.
    function _getBatchId(uint256 _tokenId) internal view returns (uint256 batchId, uint256 index) {
        uint256 numOfTokenBatches = getBaseURICount();
        uint256[] memory indices = batchIds;

        for (uint256 i = 0; i < numOfTokenBatches; i += 1) {
            if (_tokenId < indices[i]) {
                index = i;
                batchId = indices[i];

                return (batchId, index);
            }
        }

        revert("Invalid tokenId");
    }

    /// @dev Returns the baseURI for a token. The intended metadata URI for the token is baseURI + tokenId.
    function _getBaseURI(uint256 _tokenId) internal view returns (string memory) {
        uint256 numOfTokenBatches = getBaseURICount();
        uint256[] memory indices = batchIds;

        for (uint256 i = 0; i < numOfTokenBatches; i += 1) {
            if (_tokenId < indices[i]) {
                return baseURI[indices[i]];
            }
        }
        revert("Invalid tokenId");
    }

    /// @dev Sets the base URI for the batch of tokens with the given batchId.
    function _setBaseURI(uint256 _batchId, string memory _baseURI) internal {
        baseURI[_batchId] = _baseURI;
    }

    /// @dev Mints a batch of tokenIds and associates a common baseURI to all those Ids.
    function _batchMintMetadata(
        uint256 _startId,
        uint256 _amountToMint,
        string memory _baseURIForTokens
    ) internal returns (uint256 nextTokenIdToMint, uint256 batchId) {
        batchId = _startId + _amountToMint;
        nextTokenIdToMint = batchId;

        batchIds.push(batchId);

        baseURI[batchId] = _baseURIForTokens;
    }
}
          

/_thirdweb-dev/contracts/extension/ContractMetadata.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IContractMetadata.sol";

/**
 *  @title   Contract Metadata
 *  @notice  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *           for you contract.
 *           Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

abstract contract ContractMetadata is IContractMetadata {
    /// @notice Returns the contract metadata URI.
    string public override contractURI;

    /**
     *  @notice         Lets a contract admin set the URI for contract-level metadata.
     *  @dev            Caller should be authorized to setup contractURI, e.g. contract admin.
     *                  See {_canSetContractURI}.
     *                  Emits {ContractURIUpdated Event}.
     *
     *  @param _uri     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     */
    function setContractURI(string memory _uri) external override {
        if (!_canSetContractURI()) {
            revert("Not authorized");
        }

        _setupContractURI(_uri);
    }

    /// @dev Lets a contract admin set the URI for contract-level metadata.
    function _setupContractURI(string memory _uri) internal {
        string memory prevURI = contractURI;
        contractURI = _uri;

        emit ContractURIUpdated(prevURI, _uri);
    }

    /// @dev Returns whether contract metadata can be set in the given execution context.
    function _canSetContractURI() internal view virtual returns (bool);
}
          

/_thirdweb-dev/contracts/extension/DefaultOperatorFilterer.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

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

/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}

    function subscribeToRegistry(address _subscription) external {
        require(_canSetOperatorRestriction(), "Not authorized to subscribe to registry.");
        _register(_subscription, true);
    }
}
          

/_thirdweb-dev/contracts/extension/Multicall.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "../lib/TWAddress.sol";
import "./interface/IMulticall.sol";

/**
 * @dev Provides a function to batch together multiple calls in a single external call.
 *
 * _Available since v4.1._
 */
contract Multicall is IMulticall {
    /**
     *  @notice Receives and executes a batch of function calls on this contract.
     *  @dev Receives and executes a batch of function calls on this contract.
     *
     *  @param data The bytes data that makes up the batch of function calls to execute.
     *  @return results The bytes data that makes up the result of the batch of function calls executed.
     */
    function multicall(bytes[] calldata data) external virtual override returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i = 0; i < data.length; i++) {
            results[i] = TWAddress.functionDelegateCall(address(this), data[i]);
        }
        return results;
    }
}
          

/_thirdweb-dev/contracts/extension/OperatorFilterToggle.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IOperatorFilterToggle.sol";

abstract contract OperatorFilterToggle is IOperatorFilterToggle {
    bool public operatorRestriction;

    function setOperatorRestriction(bool _restriction) external {
        require(_canSetOperatorRestriction(), "Not authorized to set operator restriction.");
        _setOperatorRestriction(_restriction);
    }

    function _setOperatorRestriction(bool _restriction) internal {
        operatorRestriction = _restriction;
        emit OperatorRestriction(_restriction);
    }

    function _canSetOperatorRestriction() internal virtual returns (bool);
}
          

/_thirdweb-dev/contracts/extension/OperatorFilterer.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IOperatorFilterRegistry.sol";
import "./OperatorFilterToggle.sol";

/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */

abstract contract OperatorFilterer is OperatorFilterToggle {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        _register(subscriptionOrRegistrantToCopy, subscribe);
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Allow spending tokens from addresses with balance
        // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
        // from an EOA.
        if (from != msg.sender) {
            _checkFilterOperator(msg.sender);
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        _checkFilterOperator(operator);
        _;
    }

    function _checkFilterOperator(address operator) internal view virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (operatorRestriction) {
            if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
                if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                    revert OperatorNotAllowed(operator);
                }
            }
        }
    }

    function _register(address subscriptionOrRegistrantToCopy, bool subscribe) internal {
        // Is the registry deployed?
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            // Is the subscription contract deployed?
            if (address(subscriptionOrRegistrantToCopy).code.length > 0) {
                // Do we want to subscribe?
                if (subscribe) {
                    OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                }
            } else {
                OPERATOR_FILTER_REGISTRY.register(address(this));
            }
        }
    }
}
          

/_thirdweb-dev/contracts/extension/Ownable.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IOwnable.sol";

/**
 *  @title   Ownable
 *  @notice  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *           who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *           information about who the contract's owner is.
 */

abstract contract Ownable is IOwnable {
    /// @dev Owner of the contract (purpose: OpenSea compatibility)
    address private _owner;

    /// @dev Reverts if caller is not the owner.
    modifier onlyOwner() {
        if (msg.sender != _owner) {
            revert("Not authorized");
        }
        _;
    }

    /**
     *  @notice Returns the owner of the contract.
     */
    function owner() public view override returns (address) {
        return _owner;
    }

    /**
     *  @notice Lets an authorized wallet set a new owner for the contract.
     *  @param _newOwner The address to set as the new owner of the contract.
     */
    function setOwner(address _newOwner) external override {
        if (!_canSetOwner()) {
            revert("Not authorized");
        }
        _setupOwner(_newOwner);
    }

    /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin.
    function _setupOwner(address _newOwner) internal {
        address _prevOwner = _owner;
        _owner = _newOwner;

        emit OwnerUpdated(_prevOwner, _newOwner);
    }

    /// @dev Returns whether owner can be set in the given execution context.
    function _canSetOwner() internal view virtual returns (bool);
}
          

/_thirdweb-dev/contracts/extension/Royalty.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IRoyalty.sol";

/**
 *  @title   Royalty
 *  @notice  Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *           the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic
 *           that uses information about royalty fees, if desired.
 *
 *  @dev     The `Royalty` contract is ERC2981 compliant.
 */

abstract contract Royalty is IRoyalty {
    /// @dev The (default) address that receives all royalty value.
    address private royaltyRecipient;

    /// @dev The (default) % of a sale to take as royalty (in basis points).
    uint16 private royaltyBps;

    /// @dev Token ID => royalty recipient and bps for token
    mapping(uint256 => RoyaltyInfo) private royaltyInfoForToken;

    /**
     *  @notice   View royalty info for a given token and sale price.
     *  @dev      Returns royalty amount and recipient for `tokenId` and `salePrice`.
     *  @param tokenId          The tokenID of the NFT for which to query royalty info.
     *  @param salePrice        Sale price of the token.
     *
     *  @return receiver        Address of royalty recipient account.
     *  @return royaltyAmount   Royalty amount calculated at current royaltyBps value.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        virtual
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        (address recipient, uint256 bps) = getRoyaltyInfoForToken(tokenId);
        receiver = recipient;
        royaltyAmount = (salePrice * bps) / 10_000;
    }

    /**
     *  @notice          View royalty info for a given token.
     *  @dev             Returns royalty recipient and bps for `_tokenId`.
     *  @param _tokenId  The tokenID of the NFT for which to query royalty info.
     */
    function getRoyaltyInfoForToken(uint256 _tokenId) public view override returns (address, uint16) {
        RoyaltyInfo memory royaltyForToken = royaltyInfoForToken[_tokenId];

        return
            royaltyForToken.recipient == address(0)
                ? (royaltyRecipient, uint16(royaltyBps))
                : (royaltyForToken.recipient, uint16(royaltyForToken.bps));
    }

    /**
     *  @notice Returns the defualt royalty recipient and BPS for this contract's NFTs.
     */
    function getDefaultRoyaltyInfo() external view override returns (address, uint16) {
        return (royaltyRecipient, uint16(royaltyBps));
    }

    /**
     *  @notice         Updates default royalty recipient and bps.
     *  @dev            Caller should be authorized to set royalty info.
     *                  See {_canSetRoyaltyInfo}.
     *                  Emits {DefaultRoyalty Event}; See {_setupDefaultRoyaltyInfo}.
     *
     *  @param _royaltyRecipient   Address to be set as default royalty recipient.
     *  @param _royaltyBps         Updated royalty bps.
     */
    function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override {
        if (!_canSetRoyaltyInfo()) {
            revert("Not authorized");
        }

        _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps);
    }

    /// @dev Lets a contract admin update the default royalty recipient and bps.
    function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal {
        if (_royaltyBps > 10_000) {
            revert("Exceeds max bps");
        }

        royaltyRecipient = _royaltyRecipient;
        royaltyBps = uint16(_royaltyBps);

        emit DefaultRoyalty(_royaltyRecipient, _royaltyBps);
    }

    /**
     *  @notice         Updates default royalty recipient and bps for a particular token.
     *  @dev            Sets royalty info for `_tokenId`. Caller should be authorized to set royalty info.
     *                  See {_canSetRoyaltyInfo}.
     *                  Emits {RoyaltyForToken Event}; See {_setupRoyaltyInfoForToken}.
     *
     *  @param _recipient   Address to be set as royalty recipient for given token Id.
     *  @param _bps         Updated royalty bps for the token Id.
     */
    function setRoyaltyInfoForToken(
        uint256 _tokenId,
        address _recipient,
        uint256 _bps
    ) external override {
        if (!_canSetRoyaltyInfo()) {
            revert("Not authorized");
        }

        _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps);
    }

    /// @dev Lets a contract admin set the royalty recipient and bps for a particular token Id.
    function _setupRoyaltyInfoForToken(
        uint256 _tokenId,
        address _recipient,
        uint256 _bps
    ) internal {
        if (_bps > 10_000) {
            revert("Exceeds max bps");
        }

        royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps });

        emit RoyaltyForToken(_tokenId, _recipient, _bps);
    }

    /// @dev Returns whether royalty info can be set in the given execution context.
    function _canSetRoyaltyInfo() internal view virtual returns (bool);
}
          

/_thirdweb-dev/contracts/extension/interface/IContractMetadata.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *  for you contract.
 *
 *  Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

interface IContractMetadata {
    /// @dev Returns the metadata URI of the contract.
    function contractURI() external view returns (string memory);

    /**
     *  @dev Sets contract URI for the storefront-level metadata of the contract.
     *       Only module admin can call this function.
     */
    function setContractURI(string calldata _uri) external;

    /// @dev Emitted when the contract URI is updated.
    event ContractURIUpdated(string prevURI, string newURI);
}
          

/_thirdweb-dev/contracts/extension/interface/IMulticall.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev Provides a function to batch together multiple calls in a single external call.
 *
 * _Available since v4.1._
 */
interface IMulticall {
    /**
     * @dev Receives and executes a batch of function calls on this contract.
     */
    function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}
          

/_thirdweb-dev/contracts/extension/interface/IOperatorFilterRegistry.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

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

    function register(address registrant) external;

    function registerAndSubscribe(address registrant, address subscription) external;

    function registerAndCopyEntries(address registrant, address registrantToCopy) external;

    function unregister(address addr) external;

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

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

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

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

    function subscribe(address registrant, address registrantToSubscribe) external;

    function unsubscribe(address registrant, bool copyExistingEntries) external;

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

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

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

    function copyEntriesOf(address registrant, address registrantToCopy) external;

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

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

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

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

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

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

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

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

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

/_thirdweb-dev/contracts/extension/interface/IOperatorFilterToggle.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

interface IOperatorFilterToggle {
    event OperatorRestriction(bool restriction);

    function operatorRestriction() external view returns (bool);

    function setOperatorRestriction(bool restriction) external;
}
          

/_thirdweb-dev/contracts/extension/interface/IOwnable.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *  who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses
 *  information about who the contract's owner is.
 */

interface IOwnable {
    /// @dev Returns the owner of the contract.
    function owner() external view returns (address);

    /// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin.
    function setOwner(address _newOwner) external;

    /// @dev Emitted when a new Owner is set.
    event OwnerUpdated(address indexed prevOwner, address indexed newOwner);
}
          

/_thirdweb-dev/contracts/extension/interface/IRoyalty.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "../../eip/interface/IERC2981.sol";

/**
 *  Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *  the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic
 *  that uses information about royalty fees, if desired.
 *
 *  The `Royalty` contract is ERC2981 compliant.
 */

interface IRoyalty is IERC2981 {
    struct RoyaltyInfo {
        address recipient;
        uint256 bps;
    }

    /// @dev Returns the royalty recipient and fee bps.
    function getDefaultRoyaltyInfo() external view returns (address, uint16);

    /// @dev Lets a module admin update the royalty bps and recipient.
    function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external;

    /// @dev Lets a module admin set the royalty recipient for a particular token Id.
    function setRoyaltyInfoForToken(
        uint256 tokenId,
        address recipient,
        uint256 bps
    ) external;

    /// @dev Returns the royalty recipient for a particular token Id.
    function getRoyaltyInfoForToken(uint256 tokenId) external view returns (address, uint16);

    /// @dev Emitted when royalty info is updated.
    event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps);

    /// @dev Emitted when royalty recipient for tokenId is set
    event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps);
}
          

/_thirdweb-dev/contracts/lib/TWAddress.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev Collection of functions related to the address type
 */
library TWAddress {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * [EIP1884](https://eips.ethereum.org/EIPS/eip-1884) increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}
          

/_thirdweb-dev/contracts/lib/TWStrings.sol

// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev String operations.
 */
library TWStrings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"address","name":"_royaltyRecipient","internalType":"address"},{"type":"uint128","name":"_royaltyBps","internalType":"uint128"}]},{"type":"event","name":"custodyTransferCompleted","inputs":[{"type":"address","name":"custodian","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"custodyTransferInitiated","inputs":[{"type":"address","name":"currentCustodian","internalType":"address","indexed":false},{"type":"address","name":"newCustodian","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptCustody","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"_address","internalType":"address"},{"type":"uint256","name":"_id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"batchBalanceOf","inputs":[{"type":"address[]","name":"_address","internalType":"address[]"},{"type":"uint256[]","name":"_id","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateRoyalty","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"uint256","name":"salePrice","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"custodian","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRoyaltyInfo","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getSymbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"intiateCustodyTransfer","inputs":[{"type":"address","name":"_newCustodian","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"newCustodian","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"reward","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"bool","name":"newCollection","internalType":"bool"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"string","name":"uri","internalType":"string"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRoyaltyInfo","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"royaltyRecipient","internalType":"address"},{"type":"uint256","name":"royaltyBps","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b50604051620092c0380380620092c0833981810160405281019062000037919062000548565b838383836040516200004990620002f5565b62000058949392919062000677565b604051809103906000f08015801562000075573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166332f0cd6460006040518263ffffffff1660e01b8152600401620001119190620006ef565b600060405180830381600087803b1580156200012c57600080fd5b505af115801562000141573d6000803e3d6000fd5b5050505060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166313af4035306040518263ffffffff1660e01b8152600401620001a091906200070c565b600060405180830381600087803b158015620001bb57600080fd5b505af1158015620001d0573d6000803e3d6000fd5b5050505033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60016040518463ffffffff1660e01b8152600401620002b793929190620007e1565b600060405180830381600087803b158015620002d257600080fd5b505af1158015620002e7573d6000803e3d6000fd5b505050505050505062000833565b616c7a806200264683390190565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200036c8262000321565b810181811067ffffffffffffffff821117156200038e576200038d62000332565b5b80604052505050565b6000620003a362000303565b9050620003b1828262000361565b919050565b600067ffffffffffffffff821115620003d457620003d362000332565b5b620003df8262000321565b9050602081019050919050565b60005b838110156200040c578082015181840152602081019050620003ef565b60008484015250505050565b60006200042f6200042984620003b6565b62000397565b9050828152602081018484840111156200044e576200044d6200031c565b5b6200045b848285620003ec565b509392505050565b600082601f8301126200047b576200047a62000317565b5b81516200048d84826020860162000418565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004c38262000496565b9050919050565b620004d581620004b6565b8114620004e157600080fd5b50565b600081519050620004f581620004ca565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b6200052281620004fb565b81146200052e57600080fd5b50565b600081519050620005428162000517565b92915050565b600080600080608085870312156200056557620005646200030d565b5b600085015167ffffffffffffffff81111562000586576200058562000312565b5b620005948782880162000463565b945050602085015167ffffffffffffffff811115620005b857620005b762000312565b5b620005c68782880162000463565b9350506040620005d987828801620004e4565b9250506060620005ec8782880162000531565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006200062182620005f8565b6200062d818562000603565b93506200063f818560208601620003ec565b6200064a8162000321565b840191505092915050565b6200066081620004b6565b82525050565b6200067181620004fb565b82525050565b6000608082019050818103600083015262000693818762000614565b90508181036020830152620006a9818662000614565b9050620006ba604083018562000655565b620006c9606083018462000666565b95945050505050565b60008115159050919050565b620006e981620006d2565b82525050565b6000602082019050620007066000830184620006de565b92915050565b600060208201905062000723600083018462000655565b92915050565b6000819050919050565b6200073e8162000729565b82525050565b7f454353544153592041524d4f522058312e302e30000000000000000000000000600082015250565b60006200077c60148362000603565b9150620007898262000744565b602082019050919050565b6000819050919050565b6000819050919050565b6000620007c9620007c3620007bd8462000794565b6200079e565b62000729565b9050919050565b620007db81620007a8565b82525050565b6000608082019050620007f8600083018662000655565b62000807602083018562000733565b81810360408301526200081a816200076d565b90506200082b6060830184620007d0565b949350505050565b611e0380620008436000396000f3fe608060405234801561001057600080fd5b50600436106100f45760003560e01c8063816ac99411610097578063b3634a6711610066578063b3634a6714610285578063b76c632b1461028f578063bd85b039146102c0578063cdaa045a146102f0576100f4565b8063816ac994146101ff578063893d20e81461021b5780638e1b72cc14610239578063b0708a3514610255576100f4565b80631a853094116100d35780631a853094146101655780631aa347dc146101955780631f8f14b6146101c5578063375b74c3146101e1576100f4565b8062fdd58e146100f9578063150704011461012957806317d7de7c14610147575b600080fd5b610113600480360381019061010e9190611066565b61030e565b60405161012091906110b5565b60405180910390f35b6101316103b4565b60405161013e9190611160565b60405180910390f35b61014f61044f565b60405161015c9190611160565b60405180910390f35b61017f600480360381019061017a919061123d565b6104ea565b60405161018c919061137c565b60405180910390f35b6101af60048036038101906101aa919061139e565b61059b565b6040516101bc9190611160565b60405180910390f35b6101df60048036038101906101da91906113cb565b610643565b005b6101e9610803565b6040516101f69190611407565b60405180910390f35b6102196004803603810190610214919061158a565b610829565b005b610223610a52565b6040516102309190611407565b60405180910390f35b610253600480360381019061024e9190611621565b610ae9565b005b61026f600480360381019061026a9190611674565b610c0d565b60405161027c91906110b5565b60405180910390f35b61028d610cb8565b005b6102a960048036038101906102a4919061139e565b610e48565b6040516102b79291906116b4565b60405180910390f35b6102da60048036038101906102d5919061139e565b610ef4565b6040516102e791906110b5565b60405180910390f35b6102f8610f98565b6040516103059190611407565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1662fdd58e84846040518363ffffffff1660e01b815260040161036b9291906116b4565b602060405180830381865afa158015610388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ac91906116f2565b905092915050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610421573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061044a919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156104bc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104e5919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634e1273f4868686866040518563ffffffff1660e01b815260040161054b9493929190611905565b600060405180830381865afa158015610568573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105919190611a03565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630e89341c836040518263ffffffff1660e01b81526004016105f691906110b5565b600060405180830381865afa158015610613573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061063c919061178f565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ca90611a98565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990611b04565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc65f9e2a8610d566a872935180ace6377b1e3fe410bcd2d72a6b703e81025133600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516107f8929190611b24565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b090611a98565b60405180910390fd5b60008251116108fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f490611b99565b60405180910390fd5b83156109b95760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85856040518563ffffffff1660e01b81526004016109829493929190611bb9565b600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b50505050610a4b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528868585856040518563ffffffff1660e01b8152600401610a189493929190611bb9565b600060405180830381600087803b158015610a3257600080fd5b505af1158015610a46573d6000803e3d6000fd5b505050505b5050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae49190611c1a565b905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7090611a98565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639bcf7a158484846040518463ffffffff1660e01b8152600401610bd693929190611c47565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b50505050505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632a55205a85856040518363ffffffff1660e01b8152600401610c6b929190611c7e565b6040805180830381865afa158015610c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cab9190611ca7565b9150508091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90611d33565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f22080e9eb6b5ce589cb46f5ffa4e1f070b144980f17689a5a43dfb481d5c83a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610e3e9190611407565b60405180910390a1565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cc157df846040518263ffffffff1660e01b8152600401610ea491906110b5565b6040805180830381865afa158015610ec0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee49190611d8d565b8061ffff16905091509150915091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd85b039836040518263ffffffff1660e01b8152600401610f5091906110b5565b602060405180830381865afa158015610f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9191906116f2565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ffd82610fd2565b9050919050565b61100d81610ff2565b811461101857600080fd5b50565b60008135905061102a81611004565b92915050565b6000819050919050565b61104381611030565b811461104e57600080fd5b50565b6000813590506110608161103a565b92915050565b6000806040838503121561107d5761107c610fc8565b5b600061108b8582860161101b565b925050602061109c85828601611051565b9150509250929050565b6110af81611030565b82525050565b60006020820190506110ca60008301846110a6565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561110a5780820151818401526020810190506110ef565b60008484015250505050565b6000601f19601f8301169050919050565b6000611132826110d0565b61113c81856110db565b935061114c8185602086016110ec565b61115581611116565b840191505092915050565b6000602082019050818103600083015261117a8184611127565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111a7576111a6611182565b5b8235905067ffffffffffffffff8111156111c4576111c3611187565b5b6020830191508360208202830111156111e0576111df61118c565b5b9250929050565b60008083601f8401126111fd576111fc611182565b5b8235905067ffffffffffffffff81111561121a57611219611187565b5b6020830191508360208202830111156112365761123561118c565b5b9250929050565b6000806000806040858703121561125757611256610fc8565b5b600085013567ffffffffffffffff81111561127557611274610fcd565b5b61128187828801611191565b9450945050602085013567ffffffffffffffff8111156112a4576112a3610fcd565b5b6112b0878288016111e7565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6112f381611030565b82525050565b600061130583836112ea565b60208301905092915050565b6000602082019050919050565b6000611329826112be565b61133381856112c9565b935061133e836112da565b8060005b8381101561136f57815161135688826112f9565b975061136183611311565b925050600181019050611342565b5085935050505092915050565b60006020820190508181036000830152611396818461131e565b905092915050565b6000602082840312156113b4576113b3610fc8565b5b60006113c284828501611051565b91505092915050565b6000602082840312156113e1576113e0610fc8565b5b60006113ef8482850161101b565b91505092915050565b61140181610ff2565b82525050565b600060208201905061141c60008301846113f8565b92915050565b60008115159050919050565b61143781611422565b811461144257600080fd5b50565b6000813590506114548161142e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61149782611116565b810181811067ffffffffffffffff821117156114b6576114b561145f565b5b80604052505050565b60006114c9610fbe565b90506114d5828261148e565b919050565b600067ffffffffffffffff8211156114f5576114f461145f565b5b6114fe82611116565b9050602081019050919050565b82818337600083830152505050565b600061152d611528846114da565b6114bf565b9050828152602081018484840111156115495761154861145a565b5b61155484828561150b565b509392505050565b600082601f83011261157157611570611182565b5b813561158184826020860161151a565b91505092915050565b600080600080600060a086880312156115a6576115a5610fc8565b5b60006115b48882890161101b565b95505060206115c588828901611445565b94505060406115d688828901611051565b935050606086013567ffffffffffffffff8111156115f7576115f6610fcd565b5b6116038882890161155c565b925050608061161488828901611051565b9150509295509295909350565b60008060006060848603121561163a57611639610fc8565b5b600061164886828701611051565b93505060206116598682870161101b565b925050604061166a86828701611051565b9150509250925092565b6000806040838503121561168b5761168a610fc8565b5b600061169985828601611051565b92505060206116aa85828601611051565b9150509250929050565b60006040820190506116c960008301856113f8565b6116d660208301846110a6565b9392505050565b6000815190506116ec8161103a565b92915050565b60006020828403121561170857611707610fc8565b5b6000611716848285016116dd565b91505092915050565b600061173261172d846114da565b6114bf565b90508281526020810184848401111561174e5761174d61145a565b5b6117598482856110ec565b509392505050565b600082601f83011261177657611775611182565b5b815161178684826020860161171f565b91505092915050565b6000602082840312156117a5576117a4610fc8565b5b600082015167ffffffffffffffff8111156117c3576117c2610fcd565b5b6117cf84828501611761565b91505092915050565b600082825260208201905092915050565b6000819050919050565b6117fc81610ff2565b82525050565b600061180e83836117f3565b60208301905092915050565b6000611829602084018461101b565b905092915050565b6000602082019050919050565b600061184a83856117d8565b9350611855826117e9565b8060005b8581101561188e5761186b828461181a565b6118758882611802565b975061188083611831565b925050600181019050611859565b5085925050509392505050565b600080fd5b82818337505050565b60006118b583856112c9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118e8576118e761189b565b5b6020830292506118f98385846118a0565b82840190509392505050565b6000604082019050818103600083015261192081868861183e565b905081810360208301526119358184866118a9565b905095945050505050565b600067ffffffffffffffff82111561195b5761195a61145f565b5b602082029050602081019050919050565b600061197f61197a84611940565b6114bf565b905080838252602082019050602084028301858111156119a2576119a161118c565b5b835b818110156119cb57806119b788826116dd565b8452602084019350506020810190506119a4565b5050509392505050565b600082601f8301126119ea576119e9611182565b5b81516119fa84826020860161196c565b91505092915050565b600060208284031215611a1957611a18610fc8565b5b600082015167ffffffffffffffff811115611a3757611a36610fcd565b5b611a43848285016119d5565b91505092915050565b7f4552523a204e4f5420435553544f4449414e0000000000000000000000000000600082015250565b6000611a826012836110db565b9150611a8d82611a4c565b602082019050919050565b60006020820190508181036000830152611ab181611a75565b9050919050565b7f4552523a205a45524f2041444452455353000000000000000000000000000000600082015250565b6000611aee6011836110db565b9150611af982611ab8565b602082019050919050565b60006020820190508181036000830152611b1d81611ae1565b9050919050565b6000604082019050611b3960008301856113f8565b611b4660208301846113f8565b9392505050565b7f4552523a20454d50545920535452494e47210000000000000000000000000000600082015250565b6000611b836012836110db565b9150611b8e82611b4d565b602082019050919050565b60006020820190508181036000830152611bb281611b76565b9050919050565b6000608082019050611bce60008301876113f8565b611bdb60208301866110a6565b8181036040830152611bed8185611127565b9050611bfc60608301846110a6565b95945050505050565b600081519050611c1481611004565b92915050565b600060208284031215611c3057611c2f610fc8565b5b6000611c3e84828501611c05565b91505092915050565b6000606082019050611c5c60008301866110a6565b611c6960208301856113f8565b611c7660408301846110a6565b949350505050565b6000604082019050611c9360008301856110a6565b611ca060208301846110a6565b9392505050565b60008060408385031215611cbe57611cbd610fc8565b5b6000611ccc85828601611c05565b9250506020611cdd858286016116dd565b9150509250929050565b7f4552523a204e4f54204e455720435553544f4449414e00000000000000000000600082015250565b6000611d1d6016836110db565b9150611d2882611ce7565b602082019050919050565b60006020820190508181036000830152611d4c81611d10565b9050919050565b600061ffff82169050919050565b611d6a81611d53565b8114611d7557600080fd5b50565b600081519050611d8781611d61565b92915050565b60008060408385031215611da457611da3610fc8565b5b6000611db285828601611c05565b9250506020611dc385828601611d78565b915050925092905056fea264697066735822122034476feec514f45deb07122ae842dbe48c437632a1c663a3b7aa60f42847255064736f6c6343000812003360806040523480156200001157600080fd5b5060405162006c7a38038062006c7a83398181016040528101906200003791906200071b565b733cc6cdda760b79bafa08df41ecfa224f810dceb660018585816000908162000061919062000a16565b50806001908162000073919062000a16565b505050620000888282620000db60201b60201c565b50506200009b33620002c060201b60201c565b620000bf82826fffffffffffffffffffffffffffffffff166200038660201b60201c565b620000d160016200048060201b60201c565b5050505062000c43565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620002bc5760008273ffffffffffffffffffffffffffffffffffffffff163b11156200023d578015620001b7576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200017d92919062000b0e565b600060405180830381600087803b1580156200019857600080fd5b505af1158015620001ad573d6000803e3d6000fd5b5050505062000237565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200020292919062000b0e565b600060405180830381600087803b1580156200021d57600080fd5b505af115801562000232573d6000803e3d6000fd5b505050505b620002bb565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000286919062000b3b565b600060405180830381600087803b158015620002a157600080fd5b505af1158015620002b6573d6000803e3d6000fd5b505050505b5b5050565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7660405160405180910390a35050565b612710811115620003ce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003c59062000bb9565b60405180910390fd5b81600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760146101000a81548161ffff021916908361ffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f90d7ec04bcb8978719414f82e52e4cb651db41d0e6f8cea6118c2191e6183adb8260405162000474919062000bec565b60405180910390a25050565b80600b60006101000a81548160ff0219169083151502179055507f38475885990d8dfe9ca01f0ef160a1b5514426eab9ddbc953a3353410ba7809681604051620004cb919062000c26565b60405180910390a150565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200053f82620004f4565b810181811067ffffffffffffffff8211171562000561576200056062000505565b5b80604052505050565b600062000576620004d6565b905062000584828262000534565b919050565b600067ffffffffffffffff821115620005a757620005a662000505565b5b620005b282620004f4565b9050602081019050919050565b60005b83811015620005df578082015181840152602081019050620005c2565b60008484015250505050565b600062000602620005fc8462000589565b6200056a565b905082815260208101848484011115620006215762000620620004ef565b5b6200062e848285620005bf565b509392505050565b600082601f8301126200064e576200064d620004ea565b5b815162000660848260208601620005eb565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620006968262000669565b9050919050565b620006a88162000689565b8114620006b457600080fd5b50565b600081519050620006c8816200069d565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b620006f581620006ce565b81146200070157600080fd5b50565b6000815190506200071581620006ea565b92915050565b60008060008060808587031215620007385762000737620004e0565b5b600085015167ffffffffffffffff811115620007595762000758620004e5565b5b620007678782880162000636565b945050602085015167ffffffffffffffff8111156200078b576200078a620004e5565b5b620007998782880162000636565b9350506040620007ac87828801620006b7565b9250506060620007bf8782880162000704565b91505092959194509250565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200081e57607f821691505b602082108103620008345762000833620007d6565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026200089e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826200085f565b620008aa86836200085f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620008f7620008f1620008eb84620008c2565b620008cc565b620008c2565b9050919050565b6000819050919050565b6200091383620008d6565b6200092b6200092282620008fe565b8484546200086c565b825550505050565b600090565b6200094262000933565b6200094f81848462000908565b505050565b5b8181101562000977576200096b60008262000938565b60018101905062000955565b5050565b601f821115620009c65762000990816200083a565b6200099b846200084f565b81016020851015620009ab578190505b620009c3620009ba856200084f565b83018262000954565b50505b505050565b600082821c905092915050565b6000620009eb60001984600802620009cb565b1980831691505092915050565b600062000a068383620009d8565b9150826002028217905092915050565b62000a2182620007cb565b67ffffffffffffffff81111562000a3d5762000a3c62000505565b5b62000a49825462000805565b62000a568282856200097b565b600060209050601f83116001811462000a8e576000841562000a79578287015190505b62000a858582620009f8565b86555062000af5565b601f19841662000a9e866200083a565b60005b8281101562000ac85784890151825560018201915060208501945060208101905062000aa1565b8683101562000ae8578489015162000ae4601f891682620009d8565b8355505b6001600288020188555050505b505050505050565b62000b088162000689565b82525050565b600060408201905062000b25600083018562000afd565b62000b34602083018462000afd565b9392505050565b600060208201905062000b52600083018462000afd565b92915050565b600082825260208201905092915050565b7f45786365656473206d6178206270730000000000000000000000000000000000600082015250565b600062000ba1600f8362000b58565b915062000bae8262000b69565b602082019050919050565b6000602082019050818103600083015262000bd48162000b92565b9050919050565b62000be681620008c2565b82525050565b600060208201905062000c03600083018462000bdb565b92915050565b60008115159050919050565b62000c208162000c09565b82525050565b600060208201905062000c3d600083018462000c15565b92915050565b6160278062000c536000396000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c806363b45e2d1161010f578063ac9650d8116100a2578063e8a3d48511610071578063e8a3d485146105cb578063e985e9c5146105e9578063f242432a14610619578063f5298aca14610635576101ef565b8063ac9650d814610530578063b03f452814610560578063b24f2d391461057c578063bd85b0391461059b576101ef565b8063949c09f7116100de578063949c09f7146104be57806395d89b41146104da5780639bcf7a15146104f8578063a22cb46514610514576101ef565b806363b45e2d1461044a5780636b20c454146104685780638da5cb5b14610484578063938e3d7b146104a2576101ef565b806332f0cd64116101875780634e1273f4116101565780634e1273f4146103c4578063504c6e01146103f457806357fd845514610412578063600dd5ea1461042e576101ef565b806332f0cd641461033b5780633b1475a71461035757806341f43434146103755780634cc157df14610393576101ef565b806313af4035116101c357806313af4035146102a25780632419f51b146102be5780632a55205a146102ee5780632eb2c2d61461031f576101ef565b8062fdd58e146101f457806301ffc9a71461022457806306fdde03146102545780630e89341c14610272575b600080fd5b61020e60048036038101906102099190613e12565b610651565b60405161021b9190613e61565b60405180910390f35b61023e60048036038101906102399190613ed4565b610676565b60405161024b9190613f1c565b60405180910390f35b61025c610770565b6040516102699190613fc7565b60405180910390f35b61028c60048036038101906102879190613fe9565b6107fe565b6040516102999190613fc7565b60405180910390f35b6102bc60048036038101906102b79190614016565b6108f4565b005b6102d860048036038101906102d39190613fe9565b610947565b6040516102e59190613e61565b60405180910390f35b61030860048036038101906103039190614043565b6109b8565b604051610316929190614092565b60405180910390f35b610339600480360381019061033491906142b8565b6109f6565b005b610355600480360381019061035091906143b3565b610a49565b005b61035f610a9c565b60405161036c9190613e61565b60405180910390f35b61037d610aa6565b60405161038a919061443f565b60405180910390f35b6103ad60048036038101906103a89190613fe9565b610ab8565b6040516103bb929190614477565b60405180910390f35b6103de60048036038101906103d99190614563565b610bc3565b6040516103eb9190614699565b60405180910390f35b6103fc610d23565b6040516104099190613f1c565b60405180910390f35b61042c60048036038101906104279190614016565b610d36565b005b61044860048036038101906104439190613e12565b610d8b565b005b610452610de0565b60405161045f9190613e61565b60405180910390f35b610482600480360381019061047d91906146bb565b610ded565b005b61048c61102e565b6040516104999190614746565b60405180910390f35b6104bc60048036038101906104b79190614802565b611058565b005b6104d860048036038101906104d3919061484b565b6110ab565b005b6104e26112d4565b6040516104ef9190613fc7565b60405180910390f35b610512600480360381019061050d9190614906565b611362565b005b61052e60048036038101906105299190614959565b6113b9565b005b61054a600480360381019061054591906149f4565b6113d2565b6040516105579190614b58565b60405180910390f35b61057a60048036038101906105759190614b7a565b6114de565b005b6105846115ee565b604051610592929190614477565b60405180910390f35b6105b560048036038101906105b09190613fe9565b61162d565b6040516105c29190613e61565b60405180910390f35b6105d3611645565b6040516105e09190613fc7565b60405180910390f35b61060360048036038101906105fe9190614bfd565b6116d3565b6040516106109190613f1c565b60405180910390f35b610633600480360381019061062e9190614c3d565b611702565b005b61064f600480360381019061064a9190614cd4565b611755565b005b6002602052816000526040600020602052806000526040600020600091509150505481565b60006301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806106d1575063d9b67a2660e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806107015750630e89341c60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061076957507f2a55205a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6000805461077d90614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546107a990614d56565b80156107f65780601f106107cb576101008083540402835291602001916107f6565b820191906000526020600020905b8154815290600101906020018083116107d957829003601f168201915b505050505081565b6060600060046000848152602001908152602001600020805461082090614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90614d56565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b505050505090506000815111156108b357809150506108ef565b60006108be846118fd565b9050806108ca85611aa2565b6040516020016108db929190614dc3565b604051602081830303815290604052925050505b919050565b6108fc611c02565b61093b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093290614e33565b60405180910390fd5b61094481611c3f565b50565b6000610951610de0565b8210610992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098990614e9f565b60405180910390fd5b600982815481106109a6576109a5614ebf565b5b90600052602060002001549050919050565b6000806000806109c786610ab8565b61ffff169150915081935061271081866109e19190614f1d565b6109eb9190614f8e565b925050509250929050565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610a3457610a3333611d05565b5b610a418686868686611e18565b505050505050565b610a51611f2b565b610a90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8790615031565b60405180910390fd5b610a9981611f68565b50565b6000600c54905090565b6daaeb6d7670e522a718067333cd4e81565b6000806000600860008581526020019081526020016000206040518060400160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614610b845780600001518160200151610bb9565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760149054906101000a900461ffff165b9250925050915091565b60608151835114610c09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c009061509d565b60405180910390fd5b6000835167ffffffffffffffff811115610c2657610c256140c0565b5b604051908082528060200260200182016040528015610c545781602001602082028036833780820191505090505b50905060005b8451811015610d185760026000868381518110610c7a57610c79614ebf565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858381518110610cd157610cd0614ebf565b5b6020026020010151815260200190815260200160002054828281518110610cfb57610cfa614ebf565b5b60200260200101818152505080610d11906150bd565b9050610c5a565b508091505092915050565b600b60009054906101000a900460ff1681565b610d3e611f2b565b610d7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7490615177565b60405180910390fd5b610d88816001611fbc565b50565b610d93612190565b610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc990614e33565b60405180910390fd5b610ddc82826121cd565b5050565b6000600980549050905090565b60003390508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610eb25750600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610ef1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee8906151e3565b60405180910390fd5b8151835114610f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2c9061524f565b60405180910390fd5b60005b835181101561101c57828181518110610f5457610f53614ebf565b5b6020026020010151600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000868481518110610fb057610faf614ebf565b5b60200260200101518152602001908152602001600020541015611008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fff906152bb565b60405180910390fd5b60018161101591906152db565b9050610f38565b506110288484846122c2565b50505050565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61106061256d565b61109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690614e33565b60405180910390fd5b6110a8816125aa565b50565b6110b3612686565b6110f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110e99061535b565b60405180910390fd5b6000825111611136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112d906153c7565b60405180910390fd5b815183511461117a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117190615433565b60405180910390fd5b6000611184610a9c565b90506000819050600080600090505b8651811015611291577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8782815181106111d0576111cf614ebf565b5b60200260200101510361122057838782815181106111f1576111f0614ebf565b5b60200260200101818152505060018461120a91906152db565b935060018261121991906152db565b915061127d565b8387828151811061123457611233614ebf565b5b60200260200101511061127c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112739061549f565b60405180910390fd5b5b60018161128a91906152db565b9050611193565b5060008111156112a9576112a68282866126c3565b50505b82600c819055506112cb87878760405180602001604052806000815250612729565b50505050505050565b600180546112e190614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461130d90614d56565b801561135a5780601f1061132f5761010080835404028352916020019161135a565b820191906000526020600020905b81548152906001019060200180831161133d57829003601f168201915b505050505081565b61136a612190565b6113a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a090614e33565b60405180910390fd5b6113b4838383612940565b505050565b816113c381611d05565b6113cd8383612a6b565b505050565b60608282905067ffffffffffffffff8111156113f1576113f06140c0565b5b60405190808252806020026020018201604052801561142457816020015b606081526020019060019003908161140f5790505b50905060005b838390508110156114d7576114a63085858481811061144c5761144b614ebf565b5b905060200281019061145e91906154ce565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050612bdc565b8282815181106114b9576114b8614ebf565b5b602002602001018190525080806114cf906150bd565b91505061142a565b5092915050565b6114e6612686565b611525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151c9061535b565b60405180910390fd5b600080611530610a9c565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8503611585578091506001600c600082825461156f91906152db565b925050819055506115808185612c09565b6115cb565b8085106115c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115be9061549f565b60405180910390fd5b8491505b6115e686838560405180602001604052806000815250612c2e565b505050505050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760149054906101000a900461ffff16915091509091565b600d6020528060005260406000206000915090505481565b6005805461165290614d56565b80601f016020809104026020016040519081016040528092919081815260200182805461167e90614d56565b80156116cb5780601f106116a0576101008083540402835291602001916116cb565b820191906000526020600020905b8154815290600101906020018083116116ae57829003601f168201915b505050505081565b60036020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b843373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146117405761173f33611d05565b5b61174d8686868686612dbd565b505050505050565b60003390508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061181a5750600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b611859576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611850906151e3565b60405180910390fd5b81600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000205410156118ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118e3906152bb565b60405180910390fd5b6118f7848484612ed0565b50505050565b60606000611909610de0565b90506000600980548060200260200160405190810160405280929190818152602001828054801561195957602002820191906000526020600020905b815481526020019060010190808311611945575b5050505050905060005b82811015611a615781818151811061197e5761197d614ebf565b5b6020026020010151851015611a4d57600a60008383815181106119a4576119a3614ebf565b5b6020026020010151815260200190815260200160002080546119c590614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546119f190614d56565b8015611a3e5780601f10611a1357610100808354040283529160200191611a3e565b820191906000526020600020905b815481529060010190602001808311611a2157829003601f168201915b50505050509350505050611a9d565b600181611a5a91906152db565b9050611963565b506040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a949061557d565b60405180910390fd5b919050565b606060008203611ae9576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611bfd565b600082905060005b60008214611b1b578080611b04906150bd565b915050600a82611b149190614f8e565b9150611af1565b60008167ffffffffffffffff811115611b3757611b366140c0565b5b6040519080825280601f01601f191660200182016040528015611b695781602001600182028036833780820191505090505b5090505b60008514611bf657600182611b82919061559d565b9150600a85611b9191906155d1565b6030611b9d91906152db565b60f81b818381518110611bb357611bb2614ebf565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85611bef9190614f8e565b9450611b6d565b8093505050505b919050565b6000611c0c61102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7660405160405180910390a35050565b600b60009054906101000a900460ff1615611e155760006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611e14576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611d91929190615602565b602060405180830381865afa158015611dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd29190615640565b611e1357806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611e0a9190614746565b60405180910390fd5b5b5b50565b3373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480611ed85750600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b611f17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f0e906156b9565b60405180910390fd5b611f2485858585856130e7565b5050505050565b6000611f3561102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b80600b60006101000a81548160ff0219169083151502179055507f38475885990d8dfe9ca01f0ef160a1b5514426eab9ddbc953a3353410ba7809681604051611fb19190613f1c565b60405180910390a150565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561218c5760008273ffffffffffffffffffffffffffffffffffffffff163b1115612111578015612090576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b8152600401612059929190615602565b600060405180830381600087803b15801561207357600080fd5b505af1158015612087573d6000803e3d6000fd5b5050505061210c565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016120d9929190615602565b600060405180830381600087803b1580156120f357600080fd5b505af1158015612107573d6000803e3d6000fd5b505050505b61218b565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b81526004016121589190614746565b600060405180830381600087803b15801561217257600080fd5b505af1158015612186573d6000803e3d6000fd5b505050505b5b5050565b600061219a61102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b612710811115612212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161220990615725565b60405180910390fd5b81600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760146101000a81548161ffff021916908361ffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167f90d7ec04bcb8978719414f82e52e4cb651db41d0e6f8cea6118c2191e6183adb826040516122b69190613e61565b60405180910390a25050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232890615791565b60405180910390fd5b8051825114612375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236c9061509d565b60405180910390fd5b6000339050612398818560008686604051806020016040528060008152506133f6565b60005b83518110156124e75760008482815181106123b9576123b8614ebf565b5b6020026020010151905060008483815181106123d8576123d7614ebf565b5b602002602001015190506000600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205490508181101561247a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612471906157fd565b60405180910390fd5b818103600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000208190555050505080806124df906150bd565b91505061239b565b50600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161255f92919061581d565b60405180910390a450505050565b600061257761102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600580546125b990614d56565b80601f01602080910402602001604051908101604052809291908181526020018280546125e590614d56565b80156126325780601f1061260757610100808354040283529160200191612632565b820191906000526020600020905b81548152906001019060200180831161261557829003601f168201915b50505050509050816005908161264891906159f6565b507fc9c7c3fe08b88b4df9d4d47ef47d2c43d55c025a0ba88ca442580ed9e7348a16818360405161267a929190615ac8565b60405180910390a15050565b600061269061102e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b60008083856126d291906152db565b9050809150600981908060018154018082558091505060019003906000526020600020016000909190919091505582600a6000838152602001908152602001600020908161272091906159f6565b50935093915050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278f90615b4b565b60405180910390fd5b81518351146127dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d39061509d565b60405180910390fd5b60003390506127f0816000878787876133f6565b60005b84518110156128aa5783818151811061280f5761280e614ebf565b5b6020026020010151600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087848151811061286b5761286a614ebf565b5b60200260200101518152602001908152602001600020600082825461289091906152db565b9250508190555080806128a2906150bd565b9150506127f3565b508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161292292919061581d565b60405180910390a46129398160008787878761356e565b5050505050565b612710811115612985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161297c90615725565b60405180910390fd5b60405180604001604052808373ffffffffffffffffffffffffffffffffffffffff168152602001828152506008600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff16837f7365cf4122f072a3365c20d54eff9b38d73c096c28e1892ec8f5b0e403a0f12d83604051612a5e9190613e61565b60405180910390a3505050565b60003390508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612ade576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ad590615bb7565b60405180910390fd5b81600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051612bcf9190613f1c565b60405180910390a3505050565b6060612c018383604051806060016040528060278152602001615fcb60279139613741565b905092915050565b80600460008481526020019081526020016000209081612c2991906159f6565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603612c9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9490615b4b565b60405180910390fd5b6000339050612cc181600087612cb28861380e565b612cbb8861380e565b876133f6565b82600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008681526020019081526020016000206000828254612d2191906152db565b925050819055508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612d9f929190615bd7565b60405180910390a4612db681600087878787613888565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161480612e7d5750600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b612ebc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eb3906156b9565b60405180910390fd5b612ec98585858585613a5b565b5050505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612f3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f3690615791565b60405180910390fd5b6000339050612f7281856000612f548761380e565b612f5d8761380e565b604051806020016040528060008152506133f6565b6000600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000205490508281101561300a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613001906157fd565b60405180910390fd5b828103600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002081905550600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6287876040516130d8929190615bd7565b60405180910390a45050505050565b815183511461312b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131229061509d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361319a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161319190615b4b565b60405180910390fd5b60003390506131ad8187878787876133f6565b60005b84518110156133615760008582815181106131ce576131cd614ebf565b5b6020026020010151905060008583815181106131ed576131ec614ebf565b5b602002602001015190506000600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205490508181101561328f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613286906157fd565b60405180910390fd5b818103600260008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008581526020019081526020016000208190555081600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000858152602001908152602001600020600082825461334691906152db565b925050819055505050508061335a906150bd565b90506131b0565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516133d892919061581d565b60405180910390a46133ee81878787878761356e565b505050505050565b613404868686868686613cd8565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036134b55760005b83518110156134b35782818151811061345757613456614ebf565b5b6020026020010151600d600086848151811061347657613475614ebf565b5b60200260200101518152602001908152602001600020600082825461349b91906152db565b92505081905550806134ac906150bd565b905061343b565b505b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036135665760005b83518110156135645782818151811061350857613507614ebf565b5b6020026020010151600d600086848151811061352757613526614ebf565b5b60200260200101518152602001908152602001600020600082825461354c919061559d565b925050819055508061355d906150bd565b90506134ec565b505b505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613739578373ffffffffffffffffffffffffffffffffffffffff1663bc197c8187878686866040518663ffffffff1660e01b81526004016135cf959493929190615c4a565b6020604051808303816000875af192505050801561360b57506040513d601f19601f820116820180604052508101906136089190615cc7565b60015b6136b057613617615d01565b806308c379a003613673575061362b615d23565b806136365750613675565b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161366a9190613fc7565b60405180910390fd5b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136a790615dff565b60405180910390fd5b63bc197c8160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161372e90615e6b565b60405180910390fd5b505b505050505050565b606061374c84613ce0565b61378b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378290615efd565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516137b39190615f59565b600060405180830381855af49150503d80600081146137ee576040519150601f19603f3d011682016040523d82523d6000602084013e6137f3565b606091505b5091509150613803828286613d03565b925050509392505050565b60606000600167ffffffffffffffff81111561382d5761382c6140c0565b5b60405190808252806020026020018201604052801561385b5781602001602082028036833780820191505090505b509050828160008151811061387357613872614ebf565b5b60200260200101818152505080915050919050565b60008473ffffffffffffffffffffffffffffffffffffffff163b1115613a53578373ffffffffffffffffffffffffffffffffffffffff1663f23a6e6187878686866040518663ffffffff1660e01b81526004016138e9959493929190615f70565b6020604051808303816000875af192505050801561392557506040513d601f19601f820116820180604052508101906139229190615cc7565b60015b6139ca57613931615d01565b806308c379a00361398d5750613945615d23565b80613950575061398f565b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139849190613fc7565b60405180910390fd5b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139c190615dff565b60405180910390fd5b63f23a6e6160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614613a51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a4890615e6b565b60405180910390fd5b505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613aca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ac190615b4b565b60405180910390fd5b6000339050613aed818787613ade8861380e565b613ae78861380e565b876133f6565b6000600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002054905083811015613b85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b7c906157fd565b60405180910390fd5b838103600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000208190555083600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008781526020019081526020016000206000828254613c3c91906152db565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628888604051613cb9929190615bd7565b60405180910390a4613ccf828888888888613888565b50505050505050565b505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315613d1357829050613d63565b600083511115613d265782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d5a9190613fc7565b60405180910390fd5b9392505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613da982613d7e565b9050919050565b613db981613d9e565b8114613dc457600080fd5b50565b600081359050613dd681613db0565b92915050565b6000819050919050565b613def81613ddc565b8114613dfa57600080fd5b50565b600081359050613e0c81613de6565b92915050565b60008060408385031215613e2957613e28613d74565b5b6000613e3785828601613dc7565b9250506020613e4885828601613dfd565b9150509250929050565b613e5b81613ddc565b82525050565b6000602082019050613e766000830184613e52565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613eb181613e7c565b8114613ebc57600080fd5b50565b600081359050613ece81613ea8565b92915050565b600060208284031215613eea57613ee9613d74565b5b6000613ef884828501613ebf565b91505092915050565b60008115159050919050565b613f1681613f01565b82525050565b6000602082019050613f316000830184613f0d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015613f71578082015181840152602081019050613f56565b60008484015250505050565b6000601f19601f8301169050919050565b6000613f9982613f37565b613fa38185613f42565b9350613fb3818560208601613f53565b613fbc81613f7d565b840191505092915050565b60006020820190508181036000830152613fe18184613f8e565b905092915050565b600060208284031215613fff57613ffe613d74565b5b600061400d84828501613dfd565b91505092915050565b60006020828403121561402c5761402b613d74565b5b600061403a84828501613dc7565b91505092915050565b6000806040838503121561405a57614059613d74565b5b600061406885828601613dfd565b925050602061407985828601613dfd565b9150509250929050565b61408c81613d9e565b82525050565b60006040820190506140a76000830185614083565b6140b46020830184613e52565b9392505050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6140f882613f7d565b810181811067ffffffffffffffff82111715614117576141166140c0565b5b80604052505050565b600061412a613d6a565b905061413682826140ef565b919050565b600067ffffffffffffffff821115614156576141556140c0565b5b602082029050602081019050919050565b600080fd5b600061417f61417a8461413b565b614120565b905080838252602082019050602084028301858111156141a2576141a1614167565b5b835b818110156141cb57806141b78882613dfd565b8452602084019350506020810190506141a4565b5050509392505050565b600082601f8301126141ea576141e96140bb565b5b81356141fa84826020860161416c565b91505092915050565b600080fd5b600067ffffffffffffffff821115614223576142226140c0565b5b61422c82613f7d565b9050602081019050919050565b82818337600083830152505050565b600061425b61425684614208565b614120565b90508281526020810184848401111561427757614276614203565b5b614282848285614239565b509392505050565b600082601f83011261429f5761429e6140bb565b5b81356142af848260208601614248565b91505092915050565b600080600080600060a086880312156142d4576142d3613d74565b5b60006142e288828901613dc7565b95505060206142f388828901613dc7565b945050604086013567ffffffffffffffff81111561431457614313613d79565b5b614320888289016141d5565b935050606086013567ffffffffffffffff81111561434157614340613d79565b5b61434d888289016141d5565b925050608086013567ffffffffffffffff81111561436e5761436d613d79565b5b61437a8882890161428a565b9150509295509295909350565b61439081613f01565b811461439b57600080fd5b50565b6000813590506143ad81614387565b92915050565b6000602082840312156143c9576143c8613d74565b5b60006143d78482850161439e565b91505092915050565b6000819050919050565b60006144056144006143fb84613d7e565b6143e0565b613d7e565b9050919050565b6000614417826143ea565b9050919050565b60006144298261440c565b9050919050565b6144398161441e565b82525050565b60006020820190506144546000830184614430565b92915050565b600061ffff82169050919050565b6144718161445a565b82525050565b600060408201905061448c6000830185614083565b6144996020830184614468565b9392505050565b600067ffffffffffffffff8211156144bb576144ba6140c0565b5b602082029050602081019050919050565b60006144df6144da846144a0565b614120565b9050808382526020820190506020840283018581111561450257614501614167565b5b835b8181101561452b57806145178882613dc7565b845260208401935050602081019050614504565b5050509392505050565b600082601f83011261454a576145496140bb565b5b813561455a8482602086016144cc565b91505092915050565b6000806040838503121561457a57614579613d74565b5b600083013567ffffffffffffffff81111561459857614597613d79565b5b6145a485828601614535565b925050602083013567ffffffffffffffff8111156145c5576145c4613d79565b5b6145d1858286016141d5565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61461081613ddc565b82525050565b60006146228383614607565b60208301905092915050565b6000602082019050919050565b6000614646826145db565b61465081856145e6565b935061465b836145f7565b8060005b8381101561468c5781516146738882614616565b975061467e8361462e565b92505060018101905061465f565b5085935050505092915050565b600060208201905081810360008301526146b3818461463b565b905092915050565b6000806000606084860312156146d4576146d3613d74565b5b60006146e286828701613dc7565b935050602084013567ffffffffffffffff81111561470357614702613d79565b5b61470f868287016141d5565b925050604084013567ffffffffffffffff8111156147305761472f613d79565b5b61473c868287016141d5565b9150509250925092565b600060208201905061475b6000830184614083565b92915050565b600067ffffffffffffffff82111561477c5761477b6140c0565b5b61478582613f7d565b9050602081019050919050565b60006147a56147a084614761565b614120565b9050828152602081018484840111156147c1576147c0614203565b5b6147cc848285614239565b509392505050565b600082601f8301126147e9576147e86140bb565b5b81356147f9848260208601614792565b91505092915050565b60006020828403121561481857614817613d74565b5b600082013567ffffffffffffffff81111561483657614835613d79565b5b614842848285016147d4565b91505092915050565b6000806000806080858703121561486557614864613d74565b5b600061487387828801613dc7565b945050602085013567ffffffffffffffff81111561489457614893613d79565b5b6148a0878288016141d5565b935050604085013567ffffffffffffffff8111156148c1576148c0613d79565b5b6148cd878288016141d5565b925050606085013567ffffffffffffffff8111156148ee576148ed613d79565b5b6148fa878288016147d4565b91505092959194509250565b60008060006060848603121561491f5761491e613d74565b5b600061492d86828701613dfd565b935050602061493e86828701613dc7565b925050604061494f86828701613dfd565b9150509250925092565b600080604083850312156149705761496f613d74565b5b600061497e85828601613dc7565b925050602061498f8582860161439e565b9150509250929050565b600080fd5b60008083601f8401126149b4576149b36140bb565b5b8235905067ffffffffffffffff8111156149d1576149d0614999565b5b6020830191508360208202830111156149ed576149ec614167565b5b9250929050565b60008060208385031215614a0b57614a0a613d74565b5b600083013567ffffffffffffffff811115614a2957614a28613d79565b5b614a358582860161499e565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000614a9482614a6d565b614a9e8185614a78565b9350614aae818560208601613f53565b614ab781613f7d565b840191505092915050565b6000614ace8383614a89565b905092915050565b6000602082019050919050565b6000614aee82614a41565b614af88185614a4c565b935083602082028501614b0a85614a5d565b8060005b85811015614b465784840389528151614b278582614ac2565b9450614b3283614ad6565b925060208a01995050600181019050614b0e565b50829750879550505050505092915050565b60006020820190508181036000830152614b728184614ae3565b905092915050565b60008060008060808587031215614b9457614b93613d74565b5b6000614ba287828801613dc7565b9450506020614bb387828801613dfd565b935050604085013567ffffffffffffffff811115614bd457614bd3613d79565b5b614be0878288016147d4565b9250506060614bf187828801613dfd565b91505092959194509250565b60008060408385031215614c1457614c13613d74565b5b6000614c2285828601613dc7565b9250506020614c3385828601613dc7565b9150509250929050565b600080600080600060a08688031215614c5957614c58613d74565b5b6000614c6788828901613dc7565b9550506020614c7888828901613dc7565b9450506040614c8988828901613dfd565b9350506060614c9a88828901613dfd565b925050608086013567ffffffffffffffff811115614cbb57614cba613d79565b5b614cc78882890161428a565b9150509295509295909350565b600080600060608486031215614ced57614cec613d74565b5b6000614cfb86828701613dc7565b9350506020614d0c86828701613dfd565b9250506040614d1d86828701613dfd565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614d6e57607f821691505b602082108103614d8157614d80614d27565b5b50919050565b600081905092915050565b6000614d9d82613f37565b614da78185614d87565b9350614db7818560208601613f53565b80840191505092915050565b6000614dcf8285614d92565b9150614ddb8284614d92565b91508190509392505050565b7f4e6f7420617574686f72697a6564000000000000000000000000000000000000600082015250565b6000614e1d600e83613f42565b9150614e2882614de7565b602082019050919050565b60006020820190508181036000830152614e4c81614e10565b9050919050565b7f496e76616c696420696e64657800000000000000000000000000000000000000600082015250565b6000614e89600d83613f42565b9150614e9482614e53565b602082019050919050565b60006020820190508181036000830152614eb881614e7c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614f2882613ddc565b9150614f3383613ddc565b9250828202614f4181613ddc565b91508282048414831517614f5857614f57614eee565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614f9982613ddc565b9150614fa483613ddc565b925082614fb457614fb3614f5f565b5b828204905092915050565b7f4e6f7420617574686f72697a656420746f20736574206f70657261746f72207260008201527f65737472696374696f6e2e000000000000000000000000000000000000000000602082015250565b600061501b602b83613f42565b915061502682614fbf565b604082019050919050565b6000602082019050818103600083015261504a8161500e565b9050919050565b7f4c454e4754485f4d49534d415443480000000000000000000000000000000000600082015250565b6000615087600f83613f42565b915061509282615051565b602082019050919050565b600060208201905081810360008301526150b68161507a565b9050919050565b60006150c882613ddc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036150fa576150f9614eee565b5b600182019050919050565b7f4e6f7420617574686f72697a656420746f2073756273637269626520746f207260008201527f656769737472792e000000000000000000000000000000000000000000000000602082015250565b6000615161602883613f42565b915061516c82615105565b604082019050919050565b6000602082019050818103600083015261519081615154565b9050919050565b7f556e617070726f7665642063616c6c6572000000000000000000000000000000600082015250565b60006151cd601183613f42565b91506151d882615197565b602082019050919050565b600060208201905081810360008301526151fc816151c0565b9050919050565b7f4c656e677468206d69736d617463680000000000000000000000000000000000600082015250565b6000615239600f83613f42565b915061524482615203565b602082019050919050565b600060208201905081810360008301526152688161522c565b9050919050565b7f4e6f7420656e6f75676820746f6b656e73206f776e6564000000000000000000600082015250565b60006152a5601783613f42565b91506152b08261526f565b602082019050919050565b600060208201905081810360008301526152d481615298565b9050919050565b60006152e682613ddc565b91506152f183613ddc565b925082820190508082111561530957615308614eee565b5b92915050565b7f4e6f7420617574686f72697a656420746f206d696e742e000000000000000000600082015250565b6000615345601783613f42565b91506153508261530f565b602082019050919050565b6000602082019050818103600083015261537481615338565b9050919050565b7f4d696e74696e67207a65726f20746f6b656e732e000000000000000000000000600082015250565b60006153b1601483613f42565b91506153bc8261537b565b602082019050919050565b600060208201905081810360008301526153e0816153a4565b9050919050565b7f4c656e677468206d69736d617463682e00000000000000000000000000000000600082015250565b600061541d601083613f42565b9150615428826153e7565b602082019050919050565b6000602082019050818103600083015261544c81615410565b9050919050565b7f696e76616c696420696400000000000000000000000000000000000000000000600082015250565b6000615489600a83613f42565b915061549482615453565b602082019050919050565b600060208201905081810360008301526154b88161547c565b9050919050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126154eb576154ea6154bf565b5b80840192508235915067ffffffffffffffff82111561550d5761550c6154c4565b5b602083019250600182023603831315615529576155286154c9565b5b509250929050565b7f496e76616c696420746f6b656e49640000000000000000000000000000000000600082015250565b6000615567600f83613f42565b915061557282615531565b602082019050919050565b600060208201905081810360008301526155968161555a565b9050919050565b60006155a882613ddc565b91506155b383613ddc565b92508282039050818111156155cb576155ca614eee565b5b92915050565b60006155dc82613ddc565b91506155e783613ddc565b9250826155f7576155f6614f5f565b5b828206905092915050565b60006040820190506156176000830185614083565b6156246020830184614083565b9392505050565b60008151905061563a81614387565b92915050565b60006020828403121561565657615655613d74565b5b60006156648482850161562b565b91505092915050565b7f214f574e45525f4f525f415050524f5645440000000000000000000000000000600082015250565b60006156a3601283613f42565b91506156ae8261566d565b602082019050919050565b600060208201905081810360008301526156d281615696565b9050919050565b7f45786365656473206d6178206270730000000000000000000000000000000000600082015250565b600061570f600f83613f42565b915061571a826156d9565b602082019050919050565b6000602082019050818103600083015261573e81615702565b9050919050565b7f46524f4d5f5a45524f5f41444452000000000000000000000000000000000000600082015250565b600061577b600e83613f42565b915061578682615745565b602082019050919050565b600060208201905081810360008301526157aa8161576e565b9050919050565b7f494e53554646494349454e545f42414c00000000000000000000000000000000600082015250565b60006157e7601083613f42565b91506157f2826157b1565b602082019050919050565b60006020820190508181036000830152615816816157da565b9050919050565b60006040820190508181036000830152615837818561463b565b9050818103602083015261584b818461463b565b90509392505050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026158b67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615879565b6158c08683615879565b95508019841693508086168417925050509392505050565b60006158f36158ee6158e984613ddc565b6143e0565b613ddc565b9050919050565b6000819050919050565b61590d836158d8565b615921615919826158fa565b848454615886565b825550505050565b600090565b615936615929565b615941818484615904565b505050565b5b818110156159655761595a60008261592e565b600181019050615947565b5050565b601f8211156159aa5761597b81615854565b61598484615869565b81016020851015615993578190505b6159a761599f85615869565b830182615946565b50505b505050565b600082821c905092915050565b60006159cd600019846008026159af565b1980831691505092915050565b60006159e683836159bc565b9150826002028217905092915050565b6159ff82613f37565b67ffffffffffffffff811115615a1857615a176140c0565b5b615a228254614d56565b615a2d828285615969565b600060209050601f831160018114615a605760008415615a4e578287015190505b615a5885826159da565b865550615ac0565b601f198416615a6e86615854565b60005b82811015615a9657848901518255600182019150602085019450602081019050615a71565b86831015615ab35784890151615aaf601f8916826159bc565b8355505b6001600288020188555050505b505050505050565b60006040820190508181036000830152615ae28185613f8e565b90508181036020830152615af68184613f8e565b90509392505050565b7f544f5f5a45524f5f414444520000000000000000000000000000000000000000600082015250565b6000615b35600c83613f42565b9150615b4082615aff565b602082019050919050565b60006020820190508181036000830152615b6481615b28565b9050919050565b7f415050524f56494e475f53454c46000000000000000000000000000000000000600082015250565b6000615ba1600e83613f42565b9150615bac82615b6b565b602082019050919050565b60006020820190508181036000830152615bd081615b94565b9050919050565b6000604082019050615bec6000830185613e52565b615bf96020830184613e52565b9392505050565b600082825260208201905092915050565b6000615c1c82614a6d565b615c268185615c00565b9350615c36818560208601613f53565b615c3f81613f7d565b840191505092915050565b600060a082019050615c5f6000830188614083565b615c6c6020830187614083565b8181036040830152615c7e818661463b565b90508181036060830152615c92818561463b565b90508181036080830152615ca68184615c11565b90509695505050505050565b600081519050615cc181613ea8565b92915050565b600060208284031215615cdd57615cdc613d74565b5b6000615ceb84828501615cb2565b91505092915050565b60008160e01c9050919050565b600060033d1115615d205760046000803e615d1d600051615cf4565b90505b90565b600060443d10615db057615d35613d6a565b60043d036004823e80513d602482011167ffffffffffffffff82111715615d5d575050615db0565b808201805167ffffffffffffffff811115615d7b5750505050615db0565b80602083010160043d038501811115615d98575050505050615db0565b615da7826020018501866140ef565b82955050505050505b90565b7f2145524331313535524543454956455200000000000000000000000000000000600082015250565b6000615de9601083613f42565b9150615df482615db3565b602082019050919050565b60006020820190508181036000830152615e1881615ddc565b9050919050565b7f544f4b454e535f52454a45435445440000000000000000000000000000000000600082015250565b6000615e55600f83613f42565b9150615e6082615e1f565b602082019050919050565b60006020820190508181036000830152615e8481615e48565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b6000615ee7602683613f42565b9150615ef282615e8b565b604082019050919050565b60006020820190508181036000830152615f1681615eda565b9050919050565b600081905092915050565b6000615f3382614a6d565b615f3d8185615f1d565b9350615f4d818560208601613f53565b80840191505092915050565b6000615f658284615f28565b915081905092915050565b600060a082019050615f856000830188614083565b615f926020830187614083565b615f9f6040830186613e52565b615fac6060830185613e52565b8181036080830152615fbe8184615c11565b9050969550505050505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201ea17aac8ef68af9bee26fc8140f381715b74493f735fed266dd7db662ef041b64736f6c63430008120033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc400000000000000000000000000000000000000000000000000000000000003e80000000000000000000000000000000000000000000000000000000000000014454353544153592047414d4520454c454d454e5400000000000000000000000000000000000000000000000000000000000000000000000000000000000000034547450000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100f45760003560e01c8063816ac99411610097578063b3634a6711610066578063b3634a6714610285578063b76c632b1461028f578063bd85b039146102c0578063cdaa045a146102f0576100f4565b8063816ac994146101ff578063893d20e81461021b5780638e1b72cc14610239578063b0708a3514610255576100f4565b80631a853094116100d35780631a853094146101655780631aa347dc146101955780631f8f14b6146101c5578063375b74c3146101e1576100f4565b8062fdd58e146100f9578063150704011461012957806317d7de7c14610147575b600080fd5b610113600480360381019061010e9190611066565b61030e565b60405161012091906110b5565b60405180910390f35b6101316103b4565b60405161013e9190611160565b60405180910390f35b61014f61044f565b60405161015c9190611160565b60405180910390f35b61017f600480360381019061017a919061123d565b6104ea565b60405161018c919061137c565b60405180910390f35b6101af60048036038101906101aa919061139e565b61059b565b6040516101bc9190611160565b60405180910390f35b6101df60048036038101906101da91906113cb565b610643565b005b6101e9610803565b6040516101f69190611407565b60405180910390f35b6102196004803603810190610214919061158a565b610829565b005b610223610a52565b6040516102309190611407565b60405180910390f35b610253600480360381019061024e9190611621565b610ae9565b005b61026f600480360381019061026a9190611674565b610c0d565b60405161027c91906110b5565b60405180910390f35b61028d610cb8565b005b6102a960048036038101906102a4919061139e565b610e48565b6040516102b79291906116b4565b60405180910390f35b6102da60048036038101906102d5919061139e565b610ef4565b6040516102e791906110b5565b60405180910390f35b6102f8610f98565b6040516103059190611407565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1662fdd58e84846040518363ffffffff1660e01b815260040161036b9291906116b4565b602060405180830381865afa158015610388573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ac91906116f2565b905092915050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610421573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061044a919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156104bc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104e5919061178f565b905090565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634e1273f4868686866040518563ffffffff1660e01b815260040161054b9493929190611905565b600060405180830381865afa158015610568573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105919190611a03565b9050949350505050565b606060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630e89341c836040518263ffffffff1660e01b81526004016105f691906110b5565b600060405180830381865afa158015610613573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061063c919061178f565b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ca90611a98565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610742576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073990611b04565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc65f9e2a8610d566a872935180ace6377b1e3fe410bcd2d72a6b703e81025133600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516107f8929190611b24565b60405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b090611a98565b60405180910390fd5b60008251116108fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f490611b99565b60405180910390fd5b83156109b95760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85856040518563ffffffff1660e01b81526004016109829493929190611bb9565b600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b50505050610a4b565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b03f4528868585856040518563ffffffff1660e01b8152600401610a189493929190611bb9565b600060405180830381600087803b158015610a3257600080fd5b505af1158015610a46573d6000803e3d6000fd5b505050505b5050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae49190611c1a565b905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7090611a98565b60405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639bcf7a158484846040518463ffffffff1660e01b8152600401610bd693929190611c47565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b50505050505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632a55205a85856040518363ffffffff1660e01b8152600401610c6b929190611c7e565b6040805180830381865afa158015610c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cab9190611ca7565b9150508091505092915050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3f90611d33565b60405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f22080e9eb6b5ce589cb46f5ffa4e1f070b144980f17689a5a43dfb481d5c83a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610e3e9190611407565b60405180910390a1565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cc157df846040518263ffffffff1660e01b8152600401610ea491906110b5565b6040805180830381865afa158015610ec0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee49190611d8d565b8061ffff16905091509150915091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663bd85b039836040518263ffffffff1660e01b8152600401610f5091906110b5565b602060405180830381865afa158015610f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9191906116f2565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610ffd82610fd2565b9050919050565b61100d81610ff2565b811461101857600080fd5b50565b60008135905061102a81611004565b92915050565b6000819050919050565b61104381611030565b811461104e57600080fd5b50565b6000813590506110608161103a565b92915050565b6000806040838503121561107d5761107c610fc8565b5b600061108b8582860161101b565b925050602061109c85828601611051565b9150509250929050565b6110af81611030565b82525050565b60006020820190506110ca60008301846110a6565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561110a5780820151818401526020810190506110ef565b60008484015250505050565b6000601f19601f8301169050919050565b6000611132826110d0565b61113c81856110db565b935061114c8185602086016110ec565b61115581611116565b840191505092915050565b6000602082019050818103600083015261117a8184611127565b905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126111a7576111a6611182565b5b8235905067ffffffffffffffff8111156111c4576111c3611187565b5b6020830191508360208202830111156111e0576111df61118c565b5b9250929050565b60008083601f8401126111fd576111fc611182565b5b8235905067ffffffffffffffff81111561121a57611219611187565b5b6020830191508360208202830111156112365761123561118c565b5b9250929050565b6000806000806040858703121561125757611256610fc8565b5b600085013567ffffffffffffffff81111561127557611274610fcd565b5b61128187828801611191565b9450945050602085013567ffffffffffffffff8111156112a4576112a3610fcd565b5b6112b0878288016111e7565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6112f381611030565b82525050565b600061130583836112ea565b60208301905092915050565b6000602082019050919050565b6000611329826112be565b61133381856112c9565b935061133e836112da565b8060005b8381101561136f57815161135688826112f9565b975061136183611311565b925050600181019050611342565b5085935050505092915050565b60006020820190508181036000830152611396818461131e565b905092915050565b6000602082840312156113b4576113b3610fc8565b5b60006113c284828501611051565b91505092915050565b6000602082840312156113e1576113e0610fc8565b5b60006113ef8482850161101b565b91505092915050565b61140181610ff2565b82525050565b600060208201905061141c60008301846113f8565b92915050565b60008115159050919050565b61143781611422565b811461144257600080fd5b50565b6000813590506114548161142e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61149782611116565b810181811067ffffffffffffffff821117156114b6576114b561145f565b5b80604052505050565b60006114c9610fbe565b90506114d5828261148e565b919050565b600067ffffffffffffffff8211156114f5576114f461145f565b5b6114fe82611116565b9050602081019050919050565b82818337600083830152505050565b600061152d611528846114da565b6114bf565b9050828152602081018484840111156115495761154861145a565b5b61155484828561150b565b509392505050565b600082601f83011261157157611570611182565b5b813561158184826020860161151a565b91505092915050565b600080600080600060a086880312156115a6576115a5610fc8565b5b60006115b48882890161101b565b95505060206115c588828901611445565b94505060406115d688828901611051565b935050606086013567ffffffffffffffff8111156115f7576115f6610fcd565b5b6116038882890161155c565b925050608061161488828901611051565b9150509295509295909350565b60008060006060848603121561163a57611639610fc8565b5b600061164886828701611051565b93505060206116598682870161101b565b925050604061166a86828701611051565b9150509250925092565b6000806040838503121561168b5761168a610fc8565b5b600061169985828601611051565b92505060206116aa85828601611051565b9150509250929050565b60006040820190506116c960008301856113f8565b6116d660208301846110a6565b9392505050565b6000815190506116ec8161103a565b92915050565b60006020828403121561170857611707610fc8565b5b6000611716848285016116dd565b91505092915050565b600061173261172d846114da565b6114bf565b90508281526020810184848401111561174e5761174d61145a565b5b6117598482856110ec565b509392505050565b600082601f83011261177657611775611182565b5b815161178684826020860161171f565b91505092915050565b6000602082840312156117a5576117a4610fc8565b5b600082015167ffffffffffffffff8111156117c3576117c2610fcd565b5b6117cf84828501611761565b91505092915050565b600082825260208201905092915050565b6000819050919050565b6117fc81610ff2565b82525050565b600061180e83836117f3565b60208301905092915050565b6000611829602084018461101b565b905092915050565b6000602082019050919050565b600061184a83856117d8565b9350611855826117e9565b8060005b8581101561188e5761186b828461181a565b6118758882611802565b975061188083611831565b925050600181019050611859565b5085925050509392505050565b600080fd5b82818337505050565b60006118b583856112c9565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156118e8576118e761189b565b5b6020830292506118f98385846118a0565b82840190509392505050565b6000604082019050818103600083015261192081868861183e565b905081810360208301526119358184866118a9565b905095945050505050565b600067ffffffffffffffff82111561195b5761195a61145f565b5b602082029050602081019050919050565b600061197f61197a84611940565b6114bf565b905080838252602082019050602084028301858111156119a2576119a161118c565b5b835b818110156119cb57806119b788826116dd565b8452602084019350506020810190506119a4565b5050509392505050565b600082601f8301126119ea576119e9611182565b5b81516119fa84826020860161196c565b91505092915050565b600060208284031215611a1957611a18610fc8565b5b600082015167ffffffffffffffff811115611a3757611a36610fcd565b5b611a43848285016119d5565b91505092915050565b7f4552523a204e4f5420435553544f4449414e0000000000000000000000000000600082015250565b6000611a826012836110db565b9150611a8d82611a4c565b602082019050919050565b60006020820190508181036000830152611ab181611a75565b9050919050565b7f4552523a205a45524f2041444452455353000000000000000000000000000000600082015250565b6000611aee6011836110db565b9150611af982611ab8565b602082019050919050565b60006020820190508181036000830152611b1d81611ae1565b9050919050565b6000604082019050611b3960008301856113f8565b611b4660208301846113f8565b9392505050565b7f4552523a20454d50545920535452494e47210000000000000000000000000000600082015250565b6000611b836012836110db565b9150611b8e82611b4d565b602082019050919050565b60006020820190508181036000830152611bb281611b76565b9050919050565b6000608082019050611bce60008301876113f8565b611bdb60208301866110a6565b8181036040830152611bed8185611127565b9050611bfc60608301846110a6565b95945050505050565b600081519050611c1481611004565b92915050565b600060208284031215611c3057611c2f610fc8565b5b6000611c3e84828501611c05565b91505092915050565b6000606082019050611c5c60008301866110a6565b611c6960208301856113f8565b611c7660408301846110a6565b949350505050565b6000604082019050611c9360008301856110a6565b611ca060208301846110a6565b9392505050565b60008060408385031215611cbe57611cbd610fc8565b5b6000611ccc85828601611c05565b9250506020611cdd858286016116dd565b9150509250929050565b7f4552523a204e4f54204e455720435553544f4449414e00000000000000000000600082015250565b6000611d1d6016836110db565b9150611d2882611ce7565b602082019050919050565b60006020820190508181036000830152611d4c81611d10565b9050919050565b600061ffff82169050919050565b611d6a81611d53565b8114611d7557600080fd5b50565b600081519050611d8781611d61565b92915050565b60008060408385031215611da457611da3610fc8565b5b6000611db285828601611c05565b9250506020611dc385828601611d78565b915050925092905056fea264697066735822122034476feec514f45deb07122ae842dbe48c437632a1c663a3b7aa60f42847255064736f6c63430008120033