ETH Price: $3,239.94 (-1.43%)

Contract

0x23Ebeb9538df8f844F774a102de27579FAb980c7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00
Transaction Hash
Method
Block
From
To
Safe Transfer Fr...207489892024-09-14 12:56:47120 days ago1726318607IN
0x23Ebeb95...9FAb980c7
0 ETH0.000094421.39245584
Set Approval For...206359982024-08-29 18:21:59136 days ago1724955719IN
0x23Ebeb95...9FAb980c7
0 ETH0.000214324.65137525
Transfer From205163312024-08-13 1:10:23152 days ago1723511423IN
0x23Ebeb95...9FAb980c7
0 ETH0.000501579.25901927
Safe Transfer Fr...195056092024-03-24 16:33:23294 days ago1711298003IN
0x23Ebeb95...9FAb980c7
0 ETH0.0014561823.60378672
Safe Transfer Fr...194753202024-03-20 10:29:35298 days ago1710930575IN
0x23Ebeb95...9FAb980c7
0 ETH0.0012834932.2347297
Send From193016152024-02-25 2:27:59322 days ago1708828079IN
0x23Ebeb95...9FAb980c7
0.00031254 ETH0.0059062824.90106808
Send From193015592024-02-25 2:16:47322 days ago1708827407IN
0x23Ebeb95...9FAb980c7
0.00061826 ETH0.0064652524.16493669
Safe Transfer Fr...191053582024-01-28 13:33:35350 days ago1706448815IN
0x23Ebeb95...9FAb980c7
0 ETH0.0006531411.47053875
Send From190994412024-01-27 17:35:35351 days ago1706376935IN
0x23Ebeb95...9FAb980c7
0.00098546 ETH0.0039982717.35663693
Send From190975892024-01-27 11:22:35351 days ago1706354555IN
0x23Ebeb95...9FAb980c7
0.00040972 ETH0.0023646810.27735534
Safe Transfer Fr...190917372024-01-26 15:41:23352 days ago1706283683IN
0x23Ebeb95...9FAb980c7
0 ETH0.0012348121.69955368
Set Approval For...190691812024-01-23 11:50:23355 days ago1706010623IN
0x23Ebeb95...9FAb980c7
0 ETH0.0007360216.00259342
Safe Transfer Fr...190486022024-01-20 14:13:59358 days ago1705760039IN
0x23Ebeb95...9FAb980c7
0 ETH0.001073718.86839071
Transfer From190152072024-01-15 22:16:23363 days ago1705356983IN
0x23Ebeb95...9FAb980c7
0 ETH0.0017450829.5682078
Transfer From190149292024-01-15 21:20:11363 days ago1705353611IN
0x23Ebeb95...9FAb980c7
0 ETH0.0008793620.98970284
Transfer From190149262024-01-15 21:19:35363 days ago1705353575IN
0x23Ebeb95...9FAb980c7
0 ETH0.000921121.99228467
Transfer From190149222024-01-15 21:18:47363 days ago1705353527IN
0x23Ebeb95...9FAb980c7
0 ETH0.0011243819.06286883
Set Approval For...190141452024-01-15 18:43:11363 days ago1705344191IN
0x23Ebeb95...9FAb980c7
0 ETH0.0016940736.83262291
Send From190083372024-01-14 23:14:35363 days ago1705274075IN
0x23Ebeb95...9FAb980c7
0.00051411 ETH0.0057832321.88546349
Send From190071992024-01-14 19:25:59364 days ago1705260359IN
0x23Ebeb95...9FAb980c7
0.00038747 ETH0.006949130.16942088
Transfer From189947962024-01-13 1:49:11365 days ago1705110551IN
0x23Ebeb95...9FAb980c7
0 ETH0.0005275514.226391
Transfer From189945682024-01-13 1:03:23365 days ago1705107803IN
0x23Ebeb95...9FAb980c7
0 ETH0.0006386117.22124793
Batch Set Truste...189943452024-01-13 0:18:47365 days ago1705105127IN
0x23Ebeb95...9FAb980c7
0 ETH0.0017201318.41610871
Set Chain Id Ind...189942902024-01-13 0:07:35365 days ago1705104455IN
0x23Ebeb95...9FAb980c7
0 ETH0.002000717.50292777
Send From189939942024-01-12 23:07:59365 days ago1705100879IN
0x23Ebeb95...9FAb980c7
0.0003582 ETH0.0066432325.1388084
View all transactions

Latest 23 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
193016152024-02-25 2:27:59322 days ago1708828079
0x23Ebeb95...9FAb980c7
0.00031254 ETH
193015592024-02-25 2:16:47322 days ago1708827407
0x23Ebeb95...9FAb980c7
0.00061826 ETH
190994412024-01-27 17:35:35351 days ago1706376935
0x23Ebeb95...9FAb980c7
0.00098546 ETH
190975892024-01-27 11:22:35351 days ago1706354555
0x23Ebeb95...9FAb980c7
0.00040972 ETH
190083372024-01-14 23:14:35363 days ago1705274075
0x23Ebeb95...9FAb980c7
0.00051411 ETH
190071992024-01-14 19:25:59364 days ago1705260359
0x23Ebeb95...9FAb980c7
0.00038747 ETH
189939942024-01-12 23:07:59365 days ago1705100879
0x23Ebeb95...9FAb980c7
0.0003582 ETH
189929082024-01-12 19:29:23366 days ago1705087763
0x23Ebeb95...9FAb980c7
0.00128362 ETH
189927312024-01-12 18:53:47366 days ago1705085627
0x23Ebeb95...9FAb980c7
0.00073837 ETH
189919982024-01-12 16:26:35366 days ago1705076795
0x23Ebeb95...9FAb980c7
0.00050683 ETH
189917932024-01-12 15:44:23366 days ago1705074263
0x23Ebeb95...9FAb980c7
0.00035096 ETH
189916482024-01-12 15:15:23366 days ago1705072523
0x23Ebeb95...9FAb980c7
0.00034848 ETH
189914422024-01-12 14:34:11366 days ago1705070051
0x23Ebeb95...9FAb980c7
0.00201291 ETH
189913842024-01-12 14:22:23366 days ago1705069343
0x23Ebeb95...9FAb980c7
0.00038273 ETH
189913282024-01-12 14:11:11366 days ago1705068671
0x23Ebeb95...9FAb980c7
0.00034961 ETH
189911552024-01-12 13:36:11366 days ago1705066571
0x23Ebeb95...9FAb980c7
0.0003553 ETH
189911072024-01-12 13:26:35366 days ago1705065995
0x23Ebeb95...9FAb980c7
0.00034868 ETH
189910522024-01-12 13:15:35366 days ago1705065335
0x23Ebeb95...9FAb980c7
0.00038746 ETH
189909792024-01-12 13:00:59366 days ago1705064459
0x23Ebeb95...9FAb980c7
0.00034878 ETH
189685702024-01-09 9:39:47369 days ago1704793187
0x23Ebeb95...9FAb980c7
0.00057079 ETH
189647592024-01-08 20:47:23370 days ago1704746843
0x23Ebeb95...9FAb980c7
0.00039754 ETH
189637782024-01-08 17:28:59370 days ago1704734939
0x23Ebeb95...9FAb980c7
0.00044171 ETH
189609362024-01-08 7:52:11370 days ago1704700331  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
YouAreHere

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 20 : YouAreHere.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./YouAreONFT721Mod.sol";
import "./interfaces/IYouAreRender.sol";

////////////////////////////////////////////////////////////////////////
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                           you                                      //
//                               are                                  //
//                                   here                             //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                                    //
//                                                       0xfff.eth    //
//                                                                    //
////////////////////////////////////////////////////////////////////////

contract YouAreHere is YouAreONFT721Mod {

    uint256 public price = 0.1 ether;
    uint256 public mintable = type(uint256).max; // not mintable by default
    address public claimableBy;
    bool public minted;
    bool internal artistProofMinted;
    address public renderContract;

    constructor() YouAreONFT721Mod() {
        _initializeOwner(tx.origin);
    }

    /*//////////////////////////////////////////////////////////////
                                ADMIN
    //////////////////////////////////////////////////////////////*/

    function setMintable(uint value) external onlyOwner {
        mintable = value;
    }

    function setPrice(uint256 _price) external onlyOwner {
        price = _price;
    }

    function setClaimable(address _claimableBy) external onlyOwner {
        claimableBy = _claimableBy;
    }

    function setRenderContract(address _renderContract) external onlyOwner {
        renderContract = _renderContract;
    }

    function setChainIdIndexLookup(uint256[] calldata chainIdsToSet, uint256 startIndex) external onlyOwner {
        _setChainIdIndexLookup(chainIdsToSet, startIndex);
    }

    function withdrawBalance(address _to) external onlyOwner {
        (bool success, ) = payable(_to).call{value: address(this).balance}("");
        require(success);
    }

    /*//////////////////////////////////////////////////////////////
                                MINTING
    //////////////////////////////////////////////////////////////*/

    function mintArtistProof(address _to) external onlyOwner {
        require(!artistProofMinted, "ALREADY_MINTED");
        // épreuve d'artiste / artist proof
        require(block.chainid == 1 || block.chainid == 11155111 || block.chainid == 31337, "NOT_MAINNET");
        artistProofMinted = true;
        _initHistory(0xfff);
        _initHistory(0xfff_fff);
        _initHistory(0xfff_fff_fff);
        _mint(_to, 0xfff);
        _mint(_to, 0xfff_fff);
        _mint(_to, 0xfff_fff_fff);
    }

    function emergencyRestore(address _to) external onlyOwner {
        require(minted, "NOT_MINTED");
        // only init history if it's not already initialized
        if (historyOfTokenId[block.chainid][0] == 0) {
            _initHistory(block.chainid);
        }
        _mint(_to, block.chainid);
    }

    function ownerMintTo(address _to) external onlyOwner {
        require(!minted, "ALREADY_MINTED");
        _initHistory(block.chainid);
        minted = true;
        _mint(_to, block.chainid);
    }

    function mint(address _to) external payable {
        require(!minted, "ALREADY_MINTED");
        require(mintable < block.timestamp, "NOT_MINTABLE");
        require(msg.value == price, "PRICE");
        _initHistory(block.chainid);
        minted = true;
        _mint(_to, block.chainid);
    }

    function claim() external payable {
        require(!minted, "ALREADY_MINTED");
        require(claimableBy == msg.sender, "NOT_CLAIMABLE");
        _initHistory(block.chainid);
        minted = true;
        _mint(msg.sender, block.chainid);
    }

    function burn(uint256 tokenId) external {
        require(_isApprovedOrOwner(msg.sender, tokenId), "YouAreHere: burn caller is not owner nor approved");
        _burn(tokenId);
    }

    /*//////////////////////////////////////////////////////////////
                                TRANSFERS
    //////////////////////////////////////////////////////////////*/

    function _debitFrom(address _from, uint16, bytes memory, uint _tokenId) internal virtual override {
        require(_isApprovedOrOwner(msg.sender, _tokenId), "YouAreHere: send caller is not owner nor approved");
        require(ERC721.ownerOf(_tokenId) == _from, "YouAreHere: send from incorrect owner");
        _burn(_tokenId);
    }

    function _creditTo(uint16, address _toAddress, uint _tokenId, uint256[4] memory _history, uint256 _transfers) internal virtual override {
        require(!_exists(_tokenId));
        _updateChainHistory(_tokenId, _history, _transfers);
        _mint(_toAddress, _tokenId);
    }

    /*//////////////////////////////////////////////////////////////
                                VIEW
    //////////////////////////////////////////////////////////////*/

    function name() public pure override returns (string memory) {
        return "You Are Here";
    }

    function symbol() public pure override returns (string memory) {
        return "YOUAREHERE";
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "NOT_FOUND");
        return IYouAreRender(renderContract).tokenURI(tokenId, _getHistoryUnpacked(tokenId), numTransferForTokenId[tokenId]);
    }

    function renderSVG(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), "NOT_FOUND");
        return IYouAreRender(renderContract).renderSVG(tokenId, _getHistoryUnpacked(tokenId));
    }

    function renderSVGBase64(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), "NOT_FOUND");
        return IYouAreRender(renderContract).renderSVGBase64(tokenId, _getHistoryUnpacked(tokenId));
    }

    function renderSVGwithHistory(uint256 tokenId, uint256[] memory history) external view returns (string memory) {
        return IYouAreRender(renderContract).renderSVG(tokenId, history);
    }

    function renderSVGBase64withHistory(uint256 tokenId, uint256[] memory history) external view returns (string memory) {
        return IYouAreRender(renderContract).renderSVGBase64(tokenId, history);
    }

    function _getHistoriesOfExisting(uint[] memory tokenIds) internal view returns (uint256[][] memory) {
        uint256[][] memory result = new uint256[][](tokenIds.length);
        for (uint i; i < tokenIds.length; i++) {
            if (_exists(tokenIds[i])) {
                result[i] = _getHistoryUnpacked(tokenIds[i]);
            }
        }
        return result;
    }

    function tokenState(
        uint[] memory tokenIds
    ) public view returns (address[] memory _owners, uint _mintable, bool _minted, uint256 _price, address _claimableBy) {
        _owners = rawOwnersOf(tokenIds);
        _mintable = mintable;
        _minted = minted;
        _price = price;
        _claimableBy = claimableBy;
    }

}

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

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

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

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

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

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

File 3 of 20 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 4 of 20 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

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

File 6 of 20 : BytesLib.sol
// SPDX-License-Identifier: Unlicense
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
pragma solidity >=0.8.0 <0.9.0;

library BytesLib {
    function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(
                0x40,
                and(
                    add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                    not(31) // Round down to the nearest 32 bytes.
                )
            )
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes.slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), and(mload(mc), mask)))

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint _start,
        uint _length
    ) internal pure returns (bytes memory) {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1, "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint _start) internal pure returns (uint) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                    // the next line is the loop condition:
                    // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint256(mc < end) + cb == 2)
                        for {

                        } eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

File 7 of 20 : ExcessivelySafeCall.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.7.6;

library ExcessivelySafeCall {
    uint constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeCall(
        address _target,
        uint _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal returns (bool, bytes memory) {
        // set up for assembly call
        uint _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := call(
                _gas, // gas
                _target, // recipient
                0, // ether value
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /// @notice Use when you _really_ really _really_ don't trust the called
    /// contract. This prevents the called contract from causing reversion of
    /// the caller in as many ways as we can.
    /// @dev The main difference between this and a solidity low-level call is
    /// that we limit the number of bytes that the callee can cause to be
    /// copied to caller memory. This prevents stupid things like malicious
    /// contracts returning 10,000,000 bytes causing a local OOG when copying
    /// to memory.
    /// @param _target The address to call
    /// @param _gas The amount of gas to forward to the remote contract
    /// @param _maxCopy The maximum number of bytes of returndata to copy
    /// to memory.
    /// @param _calldata The data to send to the remote contract
    /// @return success and returndata, as `.call()`. Returndata is capped to
    /// `_maxCopy` bytes.
    function excessivelySafeStaticCall(
        address _target,
        uint _gas,
        uint16 _maxCopy,
        bytes memory _calldata
    ) internal view returns (bool, bytes memory) {
        // set up for assembly call
        uint _toCopy;
        bool _success;
        bytes memory _returnData = new bytes(_maxCopy);
        // dispatch message to recipient
        // by assembly calling "handle" function
        // we call via assembly to avoid memcopying a very large returndata
        // returned by a malicious contract
        assembly {
            _success := staticcall(
                _gas, // gas
                _target, // recipient
                add(_calldata, 0x20), // inloc
                mload(_calldata), // inlen
                0, // outloc
                0 // outlen
            )
            // limit our copy to 256 bytes
            _toCopy := returndatasize()
            if gt(_toCopy, _maxCopy) {
                _toCopy := _maxCopy
            }
            // Store the length of the copied bytes
            mstore(_returnData, _toCopy)
            // copy the bytes from returndata[0:_toCopy]
            returndatacopy(add(_returnData, 0x20), 0, _toCopy)
        }
        return (_success, _returnData);
    }

    /**
     * @notice Swaps function selectors in encoded contract calls
     * @dev Allows reuse of encoded calldata for functions with identical
     * argument types but different names. It simply swaps out the first 4 bytes
     * for the new selector. This function modifies memory in place, and should
     * only be used with caution.
     * @param _newSelector The new 4-byte selector
     * @param _buf The encoded contract args
     */
    function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure {
        require(_buf.length >= 4);
        uint _mask = LOW_28_MASK;
        assembly {
            // load the first word of
            let _word := mload(add(_buf, 0x20))
            // mask out the top 4 bytes
            // /x
            _word := and(_word, _mask)
            _word := or(_newSelector, _word)
            mstore(add(_buf, 0x20), _word)
        }
    }
}

File 8 of 20 : ILayerZeroEndpoint.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

import "./ILayerZeroUserApplicationConfig.sol";

interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.
    // @param _dstChainId - the destination chain identifier
    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains
    // @param _payload - a custom bytes payload to send to the destination contract
    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address
    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction
    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination
    function send(
        uint16 _dstChainId,
        bytes calldata _destination,
        bytes calldata _payload,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes calldata _adapterParams
    ) external payable;

    // @notice used by the messaging library to publish verified payload
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source contract (as bytes) at the source chain
    // @param _dstAddress - the address on destination chain
    // @param _nonce - the unbound message ordering nonce
    // @param _gasLimit - the gas limit for external contract execution
    // @param _payload - verified payload to send to the destination contract
    function receivePayload(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        address _dstAddress,
        uint64 _nonce,
        uint _gasLimit,
        bytes calldata _payload
    ) external;

    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);

    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM
    // @param _srcAddress - the source chain contract address
    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);

    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery
    // @param _dstChainId - the destination chain identifier
    // @param _userApplication - the user app address on this EVM chain
    // @param _payload - the custom message to send over LayerZero
    // @param _payInZRO - if false, user app pays the protocol fee in native token
    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain
    function estimateFees(
        uint16 _dstChainId,
        address _userApplication,
        bytes calldata _payload,
        bool _payInZRO,
        bytes calldata _adapterParam
    ) external view returns (uint nativeFee, uint zroFee);

    // @notice get this Endpoint's immutable source identifier
    function getChainId() external view returns (uint16);

    // @notice the interface to retry failed message on this Endpoint destination
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    // @param _payload - the payload to be retried
    function retryPayload(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        bytes calldata _payload
    ) external;

    // @notice query if any STORED payload (message blocking) at the endpoint.
    // @param _srcChainId - the source chain identifier
    // @param _srcAddress - the source chain contract address
    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);

    // @notice query if the _libraryAddress is valid for sending msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getSendLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the _libraryAddress is valid for receiving msgs.
    // @param _userApplication - the user app address on this EVM chain
    function getReceiveLibraryAddress(address _userApplication) external view returns (address);

    // @notice query if the non-reentrancy guard for send() is on
    // @return true if the guard is on. false otherwise
    function isSendingPayload() external view returns (bool);

    // @notice query if the non-reentrancy guard for receive() is on
    // @return true if the guard is on. false otherwise
    function isReceivingPayload() external view returns (bool);

    // @notice get the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _userApplication - the contract address of the user application
    // @param _configType - type of configuration. every messaging library has its own convention.
    function getConfig(
        uint16 _version,
        uint16 _chainId,
        address _userApplication,
        uint _configType
    ) external view returns (bytes memory);

    // @notice get the send() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getSendVersion(address _userApplication) external view returns (uint16);

    // @notice get the lzReceive() LayerZero messaging library version
    // @param _userApplication - the contract address of the user application
    function getReceiveVersion(address _userApplication) external view returns (uint16);
}

File 9 of 20 : ILayerZeroReceiver.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

interface ILayerZeroReceiver {
    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination
    // @param _srcChainId - the source endpoint identifier
    // @param _srcAddress - the source sending contract address from the source chain
    // @param _nonce - the ordered message nonce
    // @param _payload - the signed payload is the UA bytes has encoded to be sent
    function lzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) external;
}

File 10 of 20 : ILayerZeroUserApplicationConfig.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

interface ILayerZeroUserApplicationConfig {
    // @notice set the configuration of the LayerZero messaging library of the specified version
    // @param _version - messaging library version
    // @param _chainId - the chainId for the pending config change
    // @param _configType - type of configuration. every messaging library has its own convention.
    // @param _config - configuration in the bytes. can encode arbitrary content.
    function setConfig(
        uint16 _version,
        uint16 _chainId,
        uint _configType,
        bytes calldata _config
    ) external;

    // @notice set the send() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setSendVersion(uint16 _version) external;

    // @notice set the lzReceive() LayerZero messaging library version to _version
    // @param _version - new messaging library version
    function setReceiveVersion(uint16 _version) external;

    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload
    // @param _srcChainId - the chainId of the source chain
    // @param _srcAddress - the contract address of the source contract at the source chain
    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}

File 11 of 20 : LzApp.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "solady/src/auth/Ownable.sol";
import "./interfaces/ILayerZeroReceiver.sol";
import "./interfaces/ILayerZeroUserApplicationConfig.sol";
import "./interfaces/ILayerZeroEndpoint.sol";
import "../libraries/BytesLib.sol";

/*
 * a generic LzReceiver implementation
 */
abstract contract LzApp is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {
    using BytesLib for bytes;

    // ua can not send payload larger than this by default, but it can be changed by the ua owner
    uint public constant DEFAULT_PAYLOAD_SIZE_LIMIT = 10_000;
    uint public constant DEFAULT_MIN_GAS_LIMIT = 150_000;

    ILayerZeroEndpoint public lzEndpoint;
    mapping(uint16 => bytes) public trustedRemoteLookup;
    mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;
    mapping(uint16 => uint) public payloadSizeLimitLookup;
    address public precrime;

    event SetPrecrime(address precrime);
    event SetTrustedRemote(uint16 _remoteChainId, bytes _path);
    event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);
    event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);

    // Note: because we need deterministic deployments we can't use a differing constructor argument
    // So we set this after deployment once which makes it effectively immutable
    function setLzEndpoint(address _lzEndpoint) external onlyOwner {
        require(address(lzEndpoint) == address(0), "LzApp: lzEndpoint already set");
        lzEndpoint = ILayerZeroEndpoint(_lzEndpoint);
    }

    function lzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public virtual override {
        // lzReceive must be called by the endpoint for security
        require(msg.sender == address(lzEndpoint), "LzApp: invalid endpoint caller");

        bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
        // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.
        require(
            _srcAddress.length == trustedRemote.length && trustedRemote.length > 0 && keccak256(_srcAddress) == keccak256(trustedRemote),
            "LzApp: invalid source sending contract"
        );

        _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging
    function _blockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual;

    function _lzSend(
        uint16 _dstChainId,
        bytes memory _payload,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams,
        uint _nativeFee
    ) internal virtual {
        bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];
        require(trustedRemote.length != 0, "LzApp: destination chain is not a trusted source");
        _checkPayloadSize(_dstChainId, _payload.length);
        lzEndpoint.send{value: _nativeFee}(_dstChainId, trustedRemote, _payload, _refundAddress, _zroPaymentAddress, _adapterParams);
    }

    function _checkGasLimit(
        uint16 _dstChainId,
        uint16 _type,
        bytes memory _adapterParams,
        uint _extraGas
    ) internal view virtual {
        uint providedGasLimit = _getGasLimit(_adapterParams);
        uint minGasLimit = minDstGasLookup[_dstChainId][_type];
        if (minGasLimit == 0) {
            // use default if not set
            minGasLimit = DEFAULT_MIN_GAS_LIMIT;
        }
        require(minGasLimit > 0, "LzApp: minGasLimit not set");
        require(providedGasLimit >= minGasLimit + _extraGas, "LzApp: gas limit is too low");
    }

    function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {
        require(_adapterParams.length >= 34, "LzApp: invalid adapterParams");
        assembly {
            gasLimit := mload(add(_adapterParams, 34))
        }
    }

    function _checkPayloadSize(uint16 _dstChainId, uint _payloadSize) internal view virtual {
        uint payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];
        if (payloadSizeLimit == 0) {
            // use default if not set
            payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;
        }
        require(_payloadSize <= payloadSizeLimit, "LzApp: payload size is too large");
    }

    //---------------------------UserApplication config----------------------------------------
    function getConfig(
        uint16 _version,
        uint16 _chainId,
        address,
        uint _configType
    ) external view returns (bytes memory) {
        return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);
    }

    // generic config for LayerZero user Application
    function setConfig(
        uint16 _version,
        uint16 _chainId,
        uint _configType,
        bytes calldata _config
    ) external override onlyOwner {
        lzEndpoint.setConfig(_version, _chainId, _configType, _config);
    }

    function setSendVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setSendVersion(_version);
    }

    function setReceiveVersion(uint16 _version) external override onlyOwner {
        lzEndpoint.setReceiveVersion(_version);
    }

    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {
        lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);
    }

    // _path = abi.encodePacked(remoteAddress, localAddress)
    // this function set the trusted path for the cross-chain communication
    function setTrustedRemote(uint16 _remoteChainId, bytes calldata _path) external onlyOwner {
        trustedRemoteLookup[_remoteChainId] = _path;
        // emit SetTrustedRemote(_remoteChainId, _path);
    }

    function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {
        trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));
        // emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);
    }


    function batchSetTrustedRemote(uint16[] calldata _remoteChainIds, bytes[] calldata _paths) external onlyOwner {
        require(_remoteChainIds.length == _paths.length, "LzApp: invalid input length");
        for (uint i = 0; i < _remoteChainIds.length; i++) {
            trustedRemoteLookup[_remoteChainIds[i]] = _paths[i];
            // emit SetTrustedRemote(_remoteChainIds[i], _paths[i]);
        }
    }

    function batchSetTrustedRemoteAddress(uint16[] calldata _remoteChainIds, bytes[] calldata _remoteAddresses) external onlyOwner {
        require(_remoteChainIds.length == _remoteAddresses.length, "LzApp: invalid input length");
        for (uint i = 0; i < _remoteChainIds.length; i++) {
            trustedRemoteLookup[_remoteChainIds[i]] = abi.encodePacked(_remoteAddresses[i], address(this));
            // emit SetTrustedRemoteAddress(_remoteChainIds[i], _remoteAddresses[i]);
        }
    }

    function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {
        bytes memory path = trustedRemoteLookup[_remoteChainId];
        require(path.length != 0, "LzApp: no trusted path record");
        return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)
    }

    function setPrecrime(address _precrime) external onlyOwner {
        precrime = _precrime;
        emit SetPrecrime(_precrime);
    }

    function setMinDstGas(
        uint16 _dstChainId,
        uint16 _packetType,
        uint _minGas
    ) external onlyOwner {
        minDstGasLookup[_dstChainId][_packetType] = _minGas;
        // emit SetMinDstGas(_dstChainId, _packetType, _minGas);
    }

    // if the size is 0, it means default size limit
    function setPayloadSizeLimit(uint16 _dstChainId, uint _size) external onlyOwner {
        payloadSizeLimitLookup[_dstChainId] = _size;
    }

    //--------------------------- VIEW FUNCTION ----------------------------------------
    function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {
        bytes memory trustedSource = trustedRemoteLookup[_srcChainId];
        return keccak256(trustedSource) == keccak256(_srcAddress);
    }
}

File 12 of 20 : NonblockingLzApp.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./LzApp.sol";
import "../libraries/ExcessivelySafeCall.sol";

/*
 * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel
 * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking
 * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)
 */
abstract contract NonblockingLzApp is LzApp {
    using ExcessivelySafeCall for address;

    constructor() LzApp() {}

    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;

    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);
    event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);

    // overriding the virtual function in LzReceiver
    function _blockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual override {
        (bool success, bytes memory reason) = address(this).excessivelySafeCall(
            gasleft(),
            150,
            abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload)
        );
        if (!success) {
            _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);
        }
    }

    function _storeFailedMessage(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload,
        bytes memory _reason
    ) internal virtual {
        failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);
        emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);
    }

    function nonblockingLzReceive(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public virtual {
        // only internal transaction
        require(msg.sender == address(this), "NonblockingLzApp: caller must be LzApp");
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
    }

    //@notice override this function
    function _nonblockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual;

    function retryMessage(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes calldata _payload
    ) public payable virtual {
        // assert there is message to retry
        bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];
        require(payloadHash != bytes32(0), "NonblockingLzApp: no stored message");
        require(keccak256(_payload) == payloadHash, "NonblockingLzApp: invalid payload");
        // clear the stored message
        failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);
        // execute the message. revert if it fails again
        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
        emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);
    }
}

File 13 of 20 : IONFT721.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0;

import "./IONFT721Core.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/**
 * @dev Interface of the ONFT standard
 */
interface IONFT721 is IONFT721Core/*, IERC721*/ {

}

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

pragma solidity >=0.5.0;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @dev Interface of the ONFT Core standard
 */
interface IONFT721Core is IERC165 {
    /**
     * @dev Emitted when `_tokenIds[]` are moved from the `_sender` to (`_dstChainId`, `_toAddress`)
     * `_nonce` is the outbound nonce from
     */
    event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes indexed _toAddress, uint[] _tokenIds);
    event ReceiveFromChain(uint16 indexed _srcChainId, bytes indexed _srcAddress, address indexed _toAddress, uint[] _tokenIds);
    event SetMinGasToTransferAndStore(uint _minGasToTransferAndStore);
    event SetDstChainIdToTransferGas(uint16 _dstChainId, uint _dstChainIdToTransferGas);
    event SetDstChainIdToBatchLimit(uint16 _dstChainId, uint _dstChainIdToBatchLimit);

    /**
     * @dev Emitted when `_payload` was received from lz, but not enough gas to deliver all tokenIds
     */
    event CreditStored(bytes32 _hashedPayload, bytes _payload);
    /**
     * @dev Emitted when `_hashedPayload` has been completely delivered
     */
    event CreditCleared(bytes32 _hashedPayload);

    /**
     * @dev send token `_tokenId` to (`_dstChainId`, `_toAddress`) from `_from`
     * `_toAddress` can be any size depending on the `dstChainId`.
     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services
     */
    function sendFrom(
        address _from,
        uint16 _dstChainId,
        bytes calldata _toAddress,
        uint _tokenId,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes calldata _adapterParams
    ) external payable;

    /**
     * @dev send tokens `_tokenIds[]` to (`_dstChainId`, `_toAddress`) from `_from`
     * `_toAddress` can be any size depending on the `dstChainId`.
     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services
     */
    function sendBatchFrom(
        address _from,
        uint16 _dstChainId,
        bytes calldata _toAddress,
        uint[] calldata _tokenIds,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes calldata _adapterParams
    ) external payable;

    /**
     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
     * _dstChainId - L0 defined chain id to send tokens too
     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
     * _tokenId - token Id to transfer
     * _useZro - indicates to use zro to pay L0 fees
     * _adapterParams - flexible bytes array to indicate messaging adapter services in L0
     */
    function estimateSendFee(
        uint16 _dstChainId,
        bytes calldata _toAddress,
        uint _tokenId,
        bool _useZro,
        bytes calldata _adapterParams
    ) external view returns (uint nativeFee, uint zroFee);

    /**
     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
     * _dstChainId - L0 defined chain id to send tokens too
     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
     * _tokenIds[] - token Ids to transfer
     * _useZro - indicates to use zro to pay L0 fees
     * _adapterParams - flexible bytes array to indicate messaging adapter services in L0
     */
    function estimateSendBatchFee(
        uint16 _dstChainId,
        bytes calldata _toAddress,
        uint[] calldata _tokenIds,
        bool _useZro,
        bytes calldata _adapterParams
    ) external view returns (uint nativeFee, uint zroFee);
}

File 15 of 20 : IYouAreRender.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

interface IYouAreRender {
    function tokenURI(uint256 tokenId, uint256[] memory history, uint256 transfers) external pure returns (string memory);

    function renderSVG(uint256 tokenId, uint256[] memory history) external pure returns (string memory);

    function renderSVGBase64(uint256 tokenId, uint256[] memory history) external pure returns (string memory);
}

File 16 of 20 : YouAreHistory.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

error YouAreHistory__ChainIndexTooLarge();

abstract contract YouAreHistory {
    uint256 public constant MAX_CHAIN_HISTORY_LENGTH = 128; // uint256[4] is 128 bytes

    mapping(uint256 => uint256) public chainIdOfIndex;
    mapping(uint256 => uint256) public indexOfChainId;
    mapping(uint256 => uint256[4]) public historyOfTokenId;
    mapping(uint256 => uint256) public numTransferForTokenId;

    function _setChainIdIndexLookup(uint256[] memory chainIdsToSet, uint256 startIndex) internal {
        if (startIndex + chainIdsToSet.length > 256) {
          revert YouAreHistory__ChainIndexTooLarge();
        }

        for (uint i; i < chainIdsToSet.length; ++i) {
          chainIdOfIndex[startIndex + i] = chainIdsToSet[i];
          indexOfChainId[chainIdsToSet[i]] = startIndex + i;
        }
    }

    function _initHistory (uint256 _tokenId) internal {
        historyOfTokenId[_tokenId][0] = indexOfChainId[block.chainid];
        numTransferForTokenId[_tokenId] = 1;
    }

    function _updateChainHistory (uint256 _tokenId, uint256[4] memory _history, uint _numTransfersSoFar) internal {
        uint256 transferIndex = _numTransfersSoFar % MAX_CHAIN_HISTORY_LENGTH;

        // Which array in the uint256[4] to index into
        uint256 historyArrayIndex = transferIndex / 32;

        // Which 8 bits to overwrite
        uint256 historyArraySubIndex = (transferIndex % 32) * 8;

        // Create bitmask to clear the 8 bits associated with the new chain index
        uint256 bitmask = ~(uint256(0xFF) << historyArraySubIndex);

        // Clear the bits
        uint256 clearedHistory = _history[historyArrayIndex] & bitmask;

        // Set the new bits
        _history[historyArrayIndex] = clearedHistory | (indexOfChainId[block.chainid] << historyArraySubIndex);

        // Store
        for (uint i = 0; i < 4; i++) {
            historyOfTokenId[_tokenId][i] = _history[i];
        }

        // store the number of transfers + 1
        numTransferForTokenId[_tokenId] = _numTransfersSoFar + 1;
    }

    function _getHistories(uint[] memory tokenIds) internal view returns (uint256[4][] memory) {
        uint256[4][] memory histories = new uint256[4][](tokenIds.length);
        for (uint i; i < tokenIds.length; i++) {
            histories[i] = historyOfTokenId[tokenIds[i]];
        }
        return histories;
    }

    function _getTransferNumbers(uint[] memory tokenIds) internal view returns (uint256[] memory) {
        uint256[] memory numTransfers = new uint256[](tokenIds.length);
        for (uint i; i < tokenIds.length; i++) {
            numTransfers[i] = numTransferForTokenId[tokenIds[i]];
        }
        return numTransfers;
    }

    function _getHistoryUnpacked(uint256 tokenId) internal view returns (uint256[] memory) {
        uint256 numTransfers = numTransferForTokenId[tokenId];
        uint256 resultLength = numTransfers > MAX_CHAIN_HISTORY_LENGTH ? MAX_CHAIN_HISTORY_LENGTH : numTransfers;
        uint256[] memory result = new uint256[](resultLength);
        uint256[4] memory history = historyOfTokenId[tokenId];
        for (uint i = 0; i < result.length; i++) {
            uint256 transferIndex = (numTransfers - 1 - i) % MAX_CHAIN_HISTORY_LENGTH; // Needs to be a rolling index
            uint256 historyArrayIndex = transferIndex / 32;
            uint256 historyArraySubIndex = (transferIndex % 32) * 8;
            uint256 chainIndex = (history[historyArrayIndex] >> historyArraySubIndex) & 0xFF;
            result[i] = chainIdOfIndex[chainIndex];
        }
        return result;
    }

    function getHistory(uint tokenId) external view returns (uint256[] memory) {
        return _getHistoryUnpacked(tokenId);
    }

    function getHistories(uint[] memory tokenIds) external view returns (uint256[][] memory) {
        uint256 [][] memory result = new uint256[][](tokenIds.length);
        for (uint i; i < tokenIds.length; i++) {
            result[i] = _getHistoryUnpacked(tokenIds[i]);
        }
        return result;
    }
}

File 17 of 20 : YouAreONFT721Core.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IONFT721Core.sol";
import "./YouAreHistory.sol";
import "../lzApp/NonblockingLzApp.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

abstract contract YouAreONFT721Core is YouAreHistory, NonblockingLzApp, ERC165, ReentrancyGuard, IONFT721Core {
    uint16 public constant FUNCTION_TYPE_SEND = 1;

    struct StoredCredit {
        uint16 srcChainId;
        address toAddress;
        uint index; // which index of the tokenIds remain
        bool creditsRemain;
    }

    uint public minGasToTransferAndStore = 150_000; // Set Default
    mapping(uint16 => uint) public dstChainIdToBatchLimit;
    mapping(uint16 => uint) public dstChainIdToTransferGas; // per transfer amount of gas required to mint/transfer on the dst
    mapping(bytes32 => StoredCredit) public storedCredits;

    constructor() NonblockingLzApp() {}

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IONFT721Core).interfaceId || super.supportsInterface(interfaceId);
    }

    function estimateSendFee(
        uint16 _dstChainId,
        bytes memory _toAddress,
        uint _tokenId,
        bool _useZro,
        bytes memory _adapterParams
    ) public view virtual override returns (uint nativeFee, uint zroFee) {
        bytes memory payload = abi.encode(_toAddress, _toSingletonArray(_tokenId), _getHistories(_toSingletonArray(_tokenId)), _getTransferNumbers(_toSingletonArray(_tokenId)));
        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
    }

    function estimateSendBatchFee(
        uint16 _dstChainId,
        bytes memory _toAddress,
        uint[] memory _tokenIds,
        bool _useZro,
        bytes memory _adapterParams
    ) public view virtual override returns (uint nativeFee, uint zroFee) {
        bytes memory payload = abi.encode(_toAddress, _tokenIds, _getHistories(_tokenIds), _getTransferNumbers(_tokenIds));
        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
    }

    function sendFrom(
        address _from,
        uint16 _dstChainId,
        bytes memory _toAddress,
        uint _tokenId,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams
    ) public payable virtual override {
        _send(
            _from,
            _dstChainId,
            _toAddress,
            _toSingletonArray(_tokenId),
            _getHistories(_toSingletonArray(_tokenId)),
            _getTransferNumbers(_toSingletonArray(_tokenId)),
            _refundAddress,
            _zroPaymentAddress,
            _adapterParams
        );
    }

    function sendBatchFrom(
        address _from,
        uint16 _dstChainId,
        bytes memory _toAddress,
        uint[] memory _tokenIds,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams
    ) public payable virtual override {
        _send(_from, _dstChainId, _toAddress, _tokenIds, _getHistories(_tokenIds), _getTransferNumbers(_tokenIds), _refundAddress, _zroPaymentAddress, _adapterParams);
    }

    function _send(
        address _from,
        uint16 _dstChainId,
        bytes memory _toAddress,
        uint[] memory _tokenIds,
        uint256[4][] memory _histories,
        uint256[] memory _transfers,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams
    ) internal virtual {
        // allow 1 by default
        require(_tokenIds.length > 0, "tokenIds[] is empty");
        require(_tokenIds.length == 1 || _tokenIds.length <= dstChainIdToBatchLimit[_dstChainId], "batch size exceeds dst batch limit");

        for (uint i = 0; i < _tokenIds.length; i++) {
            _debitFrom(_from, _dstChainId, _toAddress, _tokenIds[i]);
        }

        bytes memory payload = abi.encode(_toAddress, _tokenIds, _histories, _transfers);

        _checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId] * _tokenIds.length);
        _lzSend(_dstChainId, payload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);
        emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
    }

    function _nonblockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 /*_nonce*/,
        bytes memory _payload
    ) internal virtual override {
        // decode and load the toAddress
        (bytes memory toAddressBytes, uint[] memory tokenIds, uint256[4][] memory histories, uint256[] memory transfers) = abi.decode(_payload, (bytes, uint[], uint256[4][], uint256[]));

        address toAddress;
        assembly {
            toAddress := mload(add(toAddressBytes, 20))
        }

        uint nextIndex = _creditTill(_srcChainId, toAddress, 0, tokenIds, histories, transfers);
        if (nextIndex < tokenIds.length) {
            // not enough gas to complete transfers, store to be cleared in another tx
            bytes32 hashedPayload = keccak256(_payload);
            storedCredits[hashedPayload] = StoredCredit(_srcChainId, toAddress, nextIndex, true);
            emit CreditStored(hashedPayload, _payload);
        }

        emit ReceiveFromChain(_srcChainId, _srcAddress, toAddress, tokenIds);
    }

    // Public function for anyone to clear and deliver the remaining batch sent tokenIds
    function clearCredits(bytes memory _payload) external virtual nonReentrant {
        bytes32 hashedPayload = keccak256(_payload);
        require(storedCredits[hashedPayload].creditsRemain, "no credits stored");

        (, uint[] memory tokenIds, uint256[4][] memory histories, uint256[] memory transfers) = abi.decode(_payload, (bytes, uint[], uint256[4][], uint256[]));

        uint nextIndex = _creditTill(
            storedCredits[hashedPayload].srcChainId,
            storedCredits[hashedPayload].toAddress,
            storedCredits[hashedPayload].index,
            tokenIds,
            histories,
            transfers
        );
        require(nextIndex > storedCredits[hashedPayload].index, "not enough gas to process credit transfer");

        if (nextIndex == tokenIds.length) {
            // cleared the credits, delete the element
            delete storedCredits[hashedPayload];
            emit CreditCleared(hashedPayload);
        } else {
            // store the next index to mint
            storedCredits[hashedPayload] = StoredCredit(
                storedCredits[hashedPayload].srcChainId,
                storedCredits[hashedPayload].toAddress,
                nextIndex,
                true
            );
        }
    }

    // When a srcChain has the ability to transfer more chainIds in a single tx than the dst can do.
    // Needs the ability to iterate and stop if the minGasToTransferAndStore is not met
    function _creditTill(
        uint16 _srcChainId,
        address _toAddress,
        uint _startIndex,
        uint[] memory _tokenIds,
        uint256[4][] memory _histories,
        uint[] memory _transfers
    ) internal returns (uint) {
        uint i = _startIndex;
        while (i < _tokenIds.length) {
            // if not enough gas to process, store this index for next loop
            if (gasleft() < minGasToTransferAndStore) break;

            _creditTo(_srcChainId, _toAddress, _tokenIds[i], _histories[i], _transfers[i]);
            i++;
        }

        // indicates the next index to send of tokenIds,
        // if i == tokenIds.length, we are finished
        return i;
    }

    function setMinGasToTransferAndStore(uint _minGasToTransferAndStore) external onlyOwner {
        require(_minGasToTransferAndStore > 0, "minGasToTransferAndStore must be > 0");
        minGasToTransferAndStore = _minGasToTransferAndStore;
        emit SetMinGasToTransferAndStore(_minGasToTransferAndStore);
    }

    // ensures enough gas in adapter params to handle batch transfer gas amounts on the dst
    function setDstChainIdToTransferGas(uint16 _dstChainId, uint _dstChainIdToTransferGas) external onlyOwner {
        require(_dstChainIdToTransferGas > 0, "dstChainIdToTransferGas must be > 0");
        dstChainIdToTransferGas[_dstChainId] = _dstChainIdToTransferGas;
        emit SetDstChainIdToTransferGas(_dstChainId, _dstChainIdToTransferGas);
    }

    // limit on src the amount of tokens to batch send
    function setDstChainIdToBatchLimit(uint16 _dstChainId, uint _dstChainIdToBatchLimit) external onlyOwner {
        require(_dstChainIdToBatchLimit > 0, "dstChainIdToBatchLimit must be > 0");
        dstChainIdToBatchLimit[_dstChainId] = _dstChainIdToBatchLimit;
        emit SetDstChainIdToBatchLimit(_dstChainId, _dstChainIdToBatchLimit);
    }

    function _debitFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint _tokenId) internal virtual;

    function _creditTo(uint16 _srcChainId, address _toAddress, uint _tokenId, uint256[4] memory _history, uint256 _transfers) internal virtual;

    function _toSingletonArray(uint element) internal pure returns (uint[] memory) {
        uint[] memory array = new uint[](1);
        array[0] = element;
        return array;
    }

    function _toSingletonArray(uint256[] memory element) internal pure returns (uint256[][] memory) {
        uint256[][] memory array = new uint256[][](1);
        array[0] = element;
        return array;
    }

    function _toSingletonArray(uint256[4] memory element) internal pure returns (uint256[4][] memory) {
        uint256[4][] memory array = new uint256[4][](1);
        array[0] = element;
        return array;
    }
}

File 18 of 20 : YouAreONFT721Mod.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IONFT721.sol";
import "./YouAreONFT721Core.sol";
import "solady/src/tokens/ERC721.sol";

abstract contract YouAreONFT721Mod is YouAreONFT721Core, ERC721, IONFT721 {
    constructor() ERC721() YouAreONFT721Core() {}

    function supportsInterface(bytes4 interfaceId) public view virtual override(YouAreONFT721Core, ERC721, IERC165) returns (bool) {
        return interfaceId == type(IONFT721).interfaceId || super.supportsInterface(interfaceId);
    }

    function rawOwnerOf(uint tokenId) public view returns (address) {
        if (_exists(tokenId)) {
            return ownerOf(tokenId);
        }
        return address(0);
    }

    function rawOwnersOf(uint[] memory tokenIds) public view returns (address[] memory) {
        address[] memory owners = new address[](tokenIds.length);
        for (uint i = 0; i < tokenIds.length; i++) {
            owners[i] = rawOwnerOf(tokenIds[i]);
        }
        return owners;
    }
}

File 19 of 20 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

File 20 of 20 : ERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple ERC721 implementation with storage hitchhiking.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol)
///
/// @dev Note:
/// - The ERC721 standard allows for self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - For performance, methods are made payable where permitted by the ERC721 standard.
/// - The `safeTransfer` functions use the identity precompile (0x4)
///   to copy memory internally.
///
/// If you are overriding:
/// - NEVER violate the ERC721 invariant:
///   the balance of an owner MUST always be equal to their number of ownership slots.
///   The transfer functions do not have an underflow guard for user token balances.
/// - Make sure all variables written to storage are properly cleaned
//    (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood).
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC721 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An account can hold up to 4294967295 tokens.
    uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Only the token owner or an approved account can manage the token.
    error NotOwnerNorApproved();

    /// @dev The token does not exist.
    error TokenDoesNotExist();

    /// @dev The token already exists.
    error TokenAlreadyExists();

    /// @dev Cannot query the balance for the zero address.
    error BalanceQueryForZeroAddress();

    /// @dev Cannot mint or transfer to the zero address.
    error TransferToZeroAddress();

    /// @dev The token must be owned by `from`.
    error TransferFromIncorrectOwner();

    /// @dev The recipient's balance has overflowed.
    error AccountBalanceOverflow();

    /// @dev Cannot safely transfer to a contract that does not implement
    /// the ERC721Receiver interface.
    error TransferToNonERC721ReceiverImplementer();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Emitted when token `id` is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    /// @dev Emitted when `owner` enables `account` to manage the `id` token.
    event Approval(address indexed owner, address indexed account, uint256 indexed id);

    /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens.
    event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`.
    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
        0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership data slot of `id` is given by:
    /// ```
    ///     mstore(0x00, id)
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
    /// ```
    /// Bits Layout:
    /// - [0..159]   `addr`
    /// - [160..255] `extraData`
    ///
    /// The approved address slot is given by: `add(1, ownershipSlot)`.
    ///
    /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip
    ///
    /// The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x1c)
    /// ```
    /// Bits Layout:
    /// - [0..31]   `balance`
    /// - [32..255] `aux`
    ///
    /// The `operator` approval slot of `owner` is given by:
    /// ```
    ///     mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
    ///     mstore(0x00, owner)
    ///     let operatorApprovalSlot := keccak256(0x0c, 0x30)
    /// ```
    uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192;

    /// @dev Pre-shifted and pre-masked constant.
    uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC721 METADATA                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the token collection name.
    function name() public view virtual returns (string memory);

    /// @dev Returns the token collection symbol.
    function symbol() public view virtual returns (string memory);

    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.
    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERC721                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function ownerOf(uint256 id) public view virtual returns (address result) {
        result = _ownerOf(id);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(result) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns the number of tokens owned by `owner`.
    ///
    /// Requirements:
    /// - `owner` must not be the zero address.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the `owner` is the zero address.
            if iszero(owner) {
                mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`.
                revert(0x1c, 0x04)
            }
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE)
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function getApproved(uint256 id) public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            if iszero(shl(96, sload(ownershipSlot))) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            result := sload(add(1, ownershipSlot))
        }
    }

    /// @dev Sets `account` as the approved account to manage token `id`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - The caller must be the owner of the token,
    ///   or an approved operator for the token owner.
    ///
    /// Emits an {Approval} event.
    function approve(address account, uint256 id) public payable virtual {
        _approve(msg.sender, account, id);
    }

    /// @dev Returns whether `operator` is approved to manage the tokens of `owner`.
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x30))
        }
    }

    /// @dev Sets whether `operator` is approved to manage the tokens of the caller.
    ///
    /// Emits an {ApprovalForAll} event.
    function setApprovalForAll(address operator, bool isApproved) public virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`msg.sender`, `operator`).
            mstore(0x1c, operator)
            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            // forgefmt: disable-next-item
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator)))
        }
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 id) public payable virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller()))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // Revert if the caller is not the owner, nor approved.
                if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function safeTransferFrom(address from, address to, uint256 id, bytes calldata data)
        public
        payable
        virtual
    {
        transferFrom(from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Returns true if this contract implements the interface defined by `interfaceId`.
    /// See: https://eips.ethereum.org/EIPS/eip-165
    /// This function call must use less than 30000 gas.
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let s := shr(224, interfaceId)
            // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.
            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL QUERY FUNCTIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if token `id` exists.
    function _exists(uint256 id) internal view virtual returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := iszero(iszero(shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))))
        }
    }

    /// @dev Returns the owner of token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _ownerOf(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            INTERNAL DATA HITCHHIKING FUNCTIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // For performance, no events are emitted for the hitchhiking setters.
    // Please emit your own events if required.

    /// @dev Returns the auxiliary data for `owner`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _getAux(address owner) internal view virtual returns (uint224 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            result := shr(32, sload(keccak256(0x0c, 0x1c)))
        }
    }

    /// @dev Set the auxiliary data for `owner` to `value`.
    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.
    /// Auxiliary data can be set for any address, even if it does not have any tokens.
    function _setAux(address owner, uint224 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            mstore(0x00, owner)
            let balanceSlot := keccak256(0x0c, 0x1c)
            let packed := sload(balanceSlot)
            sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed)))))
        }
    }

    /// @dev Returns the extra data for token `id`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _getExtraData(uint256 id) internal view virtual returns (uint96 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Sets the extra data for token `id` to `value`.
    /// Minting, transferring, burning a token will not change the extra data.
    /// The extra data can be set on a non-existent token.
    function _setExtraData(uint256 id, uint96 value) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let packed := sload(ownershipSlot)
            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 id) internal virtual {
        _beforeTokenTransfer(address(0), to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            to := shr(96, shl(96, to))
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Revert if the token already exists.
            if shl(96, ownershipPacked) {
                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.
                revert(0x1c, 0x04)
            }
            // Update with the owner.
            sstore(ownershipSlot, or(ownershipPacked, to))
            // Increment the balance of the owner.
            {
                mstore(0x00, to)
                let balanceSlot := keccak256(0x0c, 0x1c)
                let balanceSlotPacked := add(sload(balanceSlot), 1)
                if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(balanceSlot, balanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)
        }
        _afterTokenTransfer(address(0), to, id);
    }

    /// @dev Equivalent to `_safeMint(to, id, "")`.
    function _safeMint(address to, uint256 id) internal virtual {
        _safeMint(to, id, "");
    }

    /// @dev Mints token `id` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must not exist.
    /// - `to` cannot be the zero address.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
        _mint(to, id);
        if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_burn(address(0), id)`.
    function _burn(uint256 id) internal virtual {
        _burn(address(0), id);
    }

    /// @dev Destroys token `id`, using `by`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _burn(address by, uint256 id) internal virtual {
        address owner = ownerOf(id);
        _beforeTokenTransfer(owner, address(0), id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            // Reload the owner in case it is changed in `_beforeTokenTransfer`.
            owner := shr(96, shl(96, ownershipPacked))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Load and check the token approval.
            {
                mstore(0x00, owner)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Clear the owner.
            sstore(ownershipSlot, xor(ownershipPacked, owner))
            // Decrement the balance of `owner`.
            {
                let balanceSlot := keccak256(0x0c, 0x1c)
                sstore(balanceSlot, sub(sload(balanceSlot), 1))
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id)
        }
        _afterTokenTransfer(owner, address(0), id);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL APPROVAL FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `account` is the owner of token `id`, or is approved to manage it.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    function _isApprovedOrOwner(address account, uint256 id)
        internal
        view
        virtual
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            // Clear the upper 96 bits.
            account := shr(96, shl(96, account))
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := shr(96, shl(96, sload(ownershipSlot)))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // Check if `account` is the `owner`.
            if iszero(eq(account, owner)) {
                mstore(0x00, owner)
                // Check if `account` is approved to manage the token.
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    result := eq(account, sload(add(1, ownershipSlot)))
                }
            }
        }
    }

    /// @dev Returns the account approved to manage token `id`.
    /// Returns the zero address instead of reverting if the token does not exist.
    function _getApproved(uint256 id) internal view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, id)
            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)
            result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Equivalent to `_approve(address(0), account, id)`.
    function _approve(address account, uint256 id) internal virtual {
        _approve(address(0), account, id);
    }

    /// @dev Sets `account` as the approved account to manage token `id`, using `by`.
    ///
    /// Requirements:
    /// - Token `id` must exist.
    /// - If `by` is not the zero address, `by` must be the owner
    ///   or an approved operator for the token owner.
    ///
    /// Emits a {Transfer} event.
    function _approve(address by, address account, uint256 id) internal virtual {
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            account := and(bitmaskAddress, account)
            by := and(bitmaskAddress, by)
            // Load the owner of the token.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let owner := and(bitmaskAddress, sload(ownershipSlot))
            // Revert if the token does not exist.
            if iszero(owner) {
                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                revert(0x1c, 0x04)
            }
            // If `by` is not the zero address, do the authorization check.
            // Revert if `by` is not the owner, nor approved.
            if iszero(or(iszero(by), eq(by, owner))) {
                mstore(0x00, owner)
                if iszero(sload(keccak256(0x0c, 0x30))) {
                    mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                    revert(0x1c, 0x04)
                }
            }
            // Sets `account` as the approved account to manage `id`.
            sstore(add(1, ownershipSlot), account)
            // Emit the {Approval} event.
            log4(codesize(), 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id)
        }
    }

    /// @dev Approve or remove the `operator` as an operator for `by`,
    /// without authorization checks.
    ///
    /// Emits an {ApprovalForAll} event.
    function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            by := shr(96, shl(96, by))
            operator := shr(96, shl(96, operator))
            // Convert to 0 or 1.
            isApproved := iszero(iszero(isApproved))
            // Update the `isApproved` for (`by`, `operator`).
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))
            mstore(0x00, by)
            sstore(keccak256(0x0c, 0x30), isApproved)
            // Emit the {ApprovalForAll} event.
            mstore(0x00, isApproved)
            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `_transfer(address(0), from, to, id)`.
    function _transfer(address from, address to, uint256 id) internal virtual {
        _transfer(address(0), from, to, id);
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    ///
    /// Emits a {Transfer} event.
    function _transfer(address by, address from, address to, uint256 id) internal virtual {
        _beforeTokenTransfer(from, to, id);
        /// @solidity memory-safe-assembly
        assembly {
            // Clear the upper 96 bits.
            let bitmaskAddress := shr(96, not(0))
            from := and(bitmaskAddress, from)
            to := and(bitmaskAddress, to)
            by := and(bitmaskAddress, by)
            // Load the ownership data.
            mstore(0x00, id)
            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))
            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))
            let ownershipPacked := sload(ownershipSlot)
            let owner := and(bitmaskAddress, ownershipPacked)
            // Revert if `from` is not the owner, or does not exist.
            if iszero(mul(owner, eq(owner, from))) {
                if iszero(owner) {
                    mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
                revert(0x1c, 0x04)
            }
            // Revert if `to` is the zero address.
            if iszero(to) {
                mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
                revert(0x1c, 0x04)
            }
            // Load, check, and update the token approval.
            {
                mstore(0x00, from)
                let approvedAddress := sload(add(1, ownershipSlot))
                // If `by` is not the zero address, do the authorization check.
                // Revert if the `by` is not the owner, nor approved.
                if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) {
                    if iszero(sload(keccak256(0x0c, 0x30))) {
                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.
                        revert(0x1c, 0x04)
                    }
                }
                // Delete the approved address if any.
                if approvedAddress { sstore(add(1, ownershipSlot), 0) }
            }
            // Update with the new owner.
            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))
            // Decrement the balance of `from`.
            {
                let fromBalanceSlot := keccak256(0x0c, 0x1c)
                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))
            }
            // Increment the balance of `to`.
            {
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x1c)
                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
                if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
                    mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
                    revert(0x1c, 0x04)
                }
                sstore(toBalanceSlot, toBalanceSlotPacked)
            }
            // Emit the {Transfer} event.
            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
        }
        _afterTokenTransfer(from, to, id);
    }

    /// @dev Equivalent to `_safeTransfer(from, to, id, "")`.
    function _safeTransfer(address from, address to, uint256 id) internal virtual {
        _safeTransfer(from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - The caller must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address from, address to, uint256 id, bytes memory data)
        internal
        virtual
    {
        _transfer(address(0), from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`.
    function _safeTransfer(address by, address from, address to, uint256 id) internal virtual {
        _safeTransfer(by, from, to, id, "");
    }

    /// @dev Transfers token `id` from `from` to `to`.
    ///
    /// Requirements:
    ///
    /// - Token `id` must exist.
    /// - `from` must be the owner of the token.
    /// - `to` cannot be the zero address.
    /// - If `by` is not the zero address,
    ///   it must be the owner of the token, or be approved to manage the token.
    /// - If `to` refers to a smart contract, it must implement
    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
    ///
    /// Emits a {Transfer} event.
    function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data)
        internal
        virtual
    {
        _transfer(by, from, to, id);
        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    HOOKS FOR OVERRIDING                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any token transfers, including minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /// @dev Hook that is called after any token transfers, including minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns if `a` has bytecode of non-zero length.
    function _hasCode(address a) private view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := extcodesize(a) // Can handle dirty upper bits.
        }
    }

    /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.
    /// Reverts if the target does not support the function correctly.
    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)
        private
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the calldata.
            let m := mload(0x40)
            let onERC721ReceivedSelector := 0x150b7a02
            mstore(m, onERC721ReceivedSelector)
            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.
            mstore(add(m, 0x40), shr(96, shl(96, from)))
            mstore(add(m, 0x60), id)
            mstore(add(m, 0x80), 0x80)
            let n := mload(data)
            mstore(add(m, 0xa0), n)
            if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }
            // Revert if the call reverts.
            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {
                if returndatasize() {
                    // Bubble up the revert if the call reverts.
                    returndatacopy(m, 0x00, returndatasize())
                    revert(m, returndatasize())
                }
            }
            // Load the returndata and compare it.
            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountBalanceOverflow","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TokenAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDoesNotExist","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"YouAreHistory__ChainIndexTooLarge","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"}],"name":"CreditCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"CreditStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":true,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":true,"internalType":"address","name":"_toAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"ReceiveFromChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"bytes","name":"_toAddress","type":"bytes"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"SetDstChainIdToBatchLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"}],"name":"SetDstChainIdToTransferGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_type","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minGasToTransferAndStore","type":"uint256"}],"name":"SetMinGasToTransferAndStore","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"precrime","type":"address"}],"name":"SetPrecrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_path","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"SetTrustedRemoteAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_MIN_GAS_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_PAYLOAD_SIZE_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FUNCTION_TYPE_SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CHAIN_HISTORY_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"_remoteChainIds","type":"uint16[]"},{"internalType":"bytes[]","name":"_paths","type":"bytes[]"}],"name":"batchSetTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"_remoteChainIds","type":"uint16[]"},{"internalType":"bytes[]","name":"_remoteAddresses","type":"bytes[]"}],"name":"batchSetTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainIdOfIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimableBy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"clearCredits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToBatchLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToTransferGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"emergencyRestore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendBatchFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"getHistories","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getHistory","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"historyOfTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"indexOfChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minGasToTransferAndStore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"mintArtistProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"nonblockingLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"numTransferForTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"ownerMintTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"payloadSizeLimitLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"rawOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"rawOwnersOf","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renderSVG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renderSVGBase64","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"name":"renderSVGBase64withHistory","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"name":"renderSVGwithHistory","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"sendBatchFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"sendFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"chainIdsToSet","type":"uint256[]"},{"internalType":"uint256","name":"startIndex","type":"uint256"}],"name":"setChainIdIndexLookup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_claimableBy","type":"address"}],"name":"setClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"setDstChainIdToBatchLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"}],"name":"setDstChainIdToTransferGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lzEndpoint","type":"address"}],"name":"setLzEndpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGas","type":"uint256"}],"name":"setMinDstGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minGasToTransferAndStore","type":"uint256"}],"name":"setMinGasToTransferAndStore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_size","type":"uint256"}],"name":"setPayloadSizeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_precrime","type":"address"}],"name":"setPrecrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_renderContract","type":"address"}],"name":"setRenderContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_path","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedCredits","outputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bool","name":"creditsRemain","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"tokenState","outputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"uint256","name":"_mintable","type":"uint256"},{"internalType":"bool","name":"_minted","type":"bool"},{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_claimableBy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawBalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052620249f0600b5567016345785d8a0000600f556000196010553480156200002a57600080fd5b506001600a556200003b3262000041565b6200007d565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b615a32806200008d6000396000f3fe6080604052600436106104e05760003560e01c80638cfd8f5c11610281578063bb0946db1161015a578063e18abcd5116100cc578063f235364111610085578063f235364114611005578063f2fde38b14611025578063f5ecbdbc14611038578063fa25f9b614611058578063fee81cf414611085578063ff6acee9146110b857600080fd5b8063e18abcd514610f1e578063e5aa1b2d14610f4b578063e9726bcb14610f7c578063e985e9c514610f9c578063eb8d72b714610fd2578063f04e283e14610ff257600080fd5b8063cbed8b9c1161011e578063cbed8b9c14610e6b578063d12473a514610e8b578063d12a4c9814610eab578063d1deba1f14610ecb578063d9331a1114610ede578063df2a5b3b14610efe57600080fd5b8063bb0946db14610dc8578063bb69985214610de8578063c446183414610e08578063c8691b2a14610e1e578063c87b56dd14610e4b57600080fd5b80639f38369a116101f3578063ab3ffb93116101b7578063ab3ffb9314610d1a578063ad5343c314610d2d578063af3fb21c14610d4d578063b353aaa714610d75578063b88d4fde14610d95578063baf3292d14610da857600080fd5b80639f38369a14610c775780639fd0bb9c14610c97578063a035b1fe14610cc4578063a22cb46514610cda578063a6c3d16514610cfa57600080fd5b806391e4bac81161024557806391e4bac814610b8a578063950c8a7414610baa57806395d89b4114610bca5780639a4526ed14610bfd5780639e8c3ec614610c2a5780639ea5d6b114610c5757600080fd5b80638cfd8f5c14610ad95780638da5cb5b14610b115780638ffa1f2a14610b2a57806390ca791914610b4a57806391b7f5ed14610b6a57600080fd5b80634ac3f4ff116103be57806368bbe82111610330578063754babe6116102e9578063754babe614610a19578063756af45f14610a39578063770e6e3214610a595780637f81be6914610a7957806380e1655214610a995780638415d21314610ab957600080fd5b806368bbe821146109875780636a6278421461099e5780636f202f2a146109b157806370a08231146109d1578063715018a6146109f15780637533d788146109f957600080fd5b806354ce6d941161038257806354ce6d94146108b057806354d1f13d146108d05780635b8c41e6146108d85780635ca2ddf1146109275780636352211e1461094757806366ad5c8a1461096757600080fd5b80634ac3f4ff146108315780634bf365df1461085e5780634e71d92d146108745780634f02c4201461087c578063519056361461089d57600080fd5b8063173db2e5116104575780633d8b38f61161041b5780633d8b38f61461077b5780633f1f4fa41461079b57806342842e0e146107c857806342966c68146107db57806342d65a8d146107fb578063482881901461081b57600080fd5b8063173db2e51461068857806322a3ecf9146106a857806323b872dd1461072b578063256929621461073e5780632a205e3d1461074657600080fd5b8063095ea7b3116104a9578063095ea7b3146105d25780630b4cad4c146105e55780630df374831461060557806310ddb13714610625578063143a555c146106455780631446644b1461067357600080fd5b80621d3567146104e557806301ffc9a71461050757806306fdde031461053c57806307e0db171461057a578063081812fc1461059a575b600080fd5b3480156104f157600080fd5b50610505610500366004614542565b6110e5565b005b34801561051357600080fd5b506105276105223660046145d5565b6112f8565b60405190151581526020015b60405180910390f35b34801561054857600080fd5b5060408051808201909152600c81526b596f7520417265204865726560a01b60208201525b604051610533919061464f565b34801561058657600080fd5b50610505610595366004614662565b611338565b3480156105a657600080fd5b506105ba6105b536600461467d565b6113a6565b6040516001600160a01b039091168152602001610533565b6105056105e03660046146b6565b6113e5565b3480156105f157600080fd5b5061050561060036600461467d565b6113f4565b34801561061157600080fd5b506105056106203660046146e2565b611494565b34801561063157600080fd5b50610505610640366004614662565b6114b3565b34801561065157600080fd5b506106656106603660046146fe565b6114f0565b604051908152602001610533565b34801561067f57600080fd5b50610665608081565b34801561069457600080fd5b506012546105ba906001600160a01b031681565b3480156106b457600080fd5b506106fc6106c336600461467d565b600e6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b0390931660208501529183015215156060820152608001610533565b610505610739366004614720565b611515565b61050561162c565b34801561075257600080fd5b5061076661076136600461485c565b61167b565b60408051928352602083019190915201610533565b34801561078757600080fd5b506105276107963660046148ea565b611756565b3480156107a757600080fd5b506106656107b6366004614662565b60076020526000908152604090205481565b6105056107d6366004614720565b611823565b3480156107e757600080fd5b506105056107f636600461467d565b611850565b34801561080757600080fd5b506105056108163660046148ea565b6118cc565b34801561082757600080fd5b50610665600b5481565b34801561083d57600080fd5b5061066561084c366004614662565b600c6020526000908152604090205481565b34801561086a57600080fd5b5061066560105481565b610505611935565b34801561088857600080fd5b5060115461052790600160a01b900460ff1681565b6105056108ab36600461493c565b6119d1565b3480156108bc57600080fd5b506105056108cb366004614a39565b611a00565b610505611a46565b3480156108e457600080fd5b506106656108f3366004614a84565b6009602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561093357600080fd5b5061056d61094236600461467d565b611a82565b34801561095357600080fd5b506105ba61096236600461467d565b611b26565b34801561097357600080fd5b50610505610982366004614542565b611b64565b34801561099357600080fd5b50610665620249f081565b6105056109ac366004614ae1565b611c40565b3480156109bd57600080fd5b506105056109cc366004614afe565b611d09565b3480156109dd57600080fd5b506106656109ec366004614ae1565b611e0e565b610505611e49565b348015610a0557600080fd5b5061056d610a14366004614662565b611e5b565b348015610a2557600080fd5b50610505610a34366004614ae1565b611ef5565b348015610a4557600080fd5b50610505610a54366004614ae1565b611f1f565b348015610a6557600080fd5b506011546105ba906001600160a01b031681565b348015610a8557600080fd5b506105ba610a9436600461467d565b611f87565b348015610aa557600080fd5b50610505610ab4366004614afe565b611fa8565b348015610ac557600080fd5b50610505610ad4366004614ae1565b61208c565b348015610ae557600080fd5b50610665610af4366004614b69565b600660209081526000928352604080842090915290825290205481565b348015610b1d57600080fd5b50638b78c6d819546105ba565b348015610b3657600080fd5b50610505610b45366004614b9c565b6120b6565b348015610b5657600080fd5b50610505610b65366004614ae1565b612385565b348015610b7657600080fd5b50610505610b8536600461467d565b6123fc565b348015610b9657600080fd5b50610505610ba536600461467d565b612409565b348015610bb657600080fd5b506008546105ba906001600160a01b031681565b348015610bd657600080fd5b5060408051808201909152600a815269594f554152454845524560b01b602082015261056d565b348015610c0957600080fd5b50610665610c1836600461467d565b60016020526000908152604090205481565b348015610c3657600080fd5b50610665610c4536600461467d565b60006020819052908152604090205481565b348015610c6357600080fd5b50610505610c723660046146e2565b612416565b348015610c8357600080fd5b5061056d610c92366004614662565b6124cd565b348015610ca357600080fd5b50610cb7610cb2366004614c61565b6125dc565b6040516105339190614cd9565b348015610cd057600080fd5b50610665600f5481565b348015610ce657600080fd5b50610505610cf5366004614cec565b612696565b348015610d0657600080fd5b50610505610d153660046148ea565b6126ec565b610505610d28366004614d18565b61273a565b348015610d3957600080fd5b50610505610d48366004614ae1565b612753565b348015610d5957600080fd5b50610d62600181565b60405161ffff9091168152602001610533565b348015610d8157600080fd5b506004546105ba906001600160a01b031681565b610505610da3366004614dcd565b61283c565b348015610db457600080fd5b50610505610dc3366004614ae1565b612890565b348015610dd457600080fd5b5061056d610de3366004614e3f565b6128e6565b348015610df457600080fd5b50610505610e03366004614ae1565b61295e565b348015610e1457600080fd5b5061066561271081565b348015610e2a57600080fd5b50610e3e610e3936600461467d565b612990565b6040516105339190614eb5565b348015610e5757600080fd5b5061056d610e6636600461467d565b61299b565b348015610e7757600080fd5b50610505610e86366004614ec8565b612a10565b348015610e9757600080fd5b50610505610ea63660046146e2565b612a88565b348015610eb757600080fd5b5061056d610ec636600461467d565b612b38565b610505610ed9366004614542565b612b7a565b348015610eea57600080fd5b50610505610ef9366004614ae1565b612d90565b348015610f0a57600080fd5b50610505610f19366004614ef7565b612e13565b348015610f2a57600080fd5b50610f3e610f39366004614c61565b612e42565b6040516105339190614f33565b348015610f5757600080fd5b50610f6b610f66366004614c61565b612ef3565b604051610533959493929190614f95565b348015610f8857600080fd5b5061056d610f97366004614e3f565b612f33565b348015610fa857600080fd5b50610527610fb7366004614fd5565b601c52670a5a2e7a000000006008526000526030600c205490565b348015610fde57600080fd5b50610505610fed3660046148ea565b612f66565b610505611000366004614ae1565b612f8c565b34801561101157600080fd5b5061076661102036600461500e565b612fc9565b610505611033366004614ae1565b612fe2565b34801561104457600080fd5b5061056d611053366004615087565b613009565b34801561106457600080fd5b50610665611073366004614662565b600d6020526000908152604090205481565b34801561109157600080fd5b506106656110a0366004614ae1565b63389a75e1600c908152600091909152602090205490565b3480156110c457600080fd5b506106656110d336600461467d565b60036020526000908152604090205481565b6004546001600160a01b031633146111445760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526005602052604081208054611162906150d4565b80601f016020809104026020016040519081016040528092919081815260200182805461118e906150d4565b80156111db5780601f106111b0576101008083540402835291602001916111db565b820191906000526020600020905b8154815290600101906020018083116111be57829003601f168201915b505050505090508051868690501480156111f6575060008151115b801561121e575080516020820120604051611214908890889061510e565b6040518091039020145b6112795760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b606482015260840161113b565b6112ef8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506130a292505050565b50505050505050565b60006001600160e01b0319821615806113325750611332826301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b92915050565b61134061311b565b600480546040516307e0db1760e01b815261ffff8416928101929092526001600160a01b0316906307e0db17906024015b600060405180830381600087803b15801561138b57600080fd5b505af115801561139f573d6000803e3d6000fd5b5050505050565b600081600052673ec412a9852d173d60c11b601c52602060002082018201805460601b6113db5763ceea21b66000526004601cfd5b6001015492915050565b6113f0338383613136565b5050565b6113fc61311b565b600081116114585760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b606482015260840161113b565b600b8190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b61149c61311b565b61ffff909116600090815260076020526040902055565b6114bb61311b565b600480546040516310ddb13760e01b815261ffff8416928101929092526001600160a01b0316906310ddb13790602401611371565b6002602052816000526040600020816004811061150c57600080fd5b01549150829050565b6000818152673ec412a9852d173d60c11b3317601c52602090208101810180546001600160a01b03948516949384169381169190828614830261157357826115655763ceea21b66000526004601cfd5b63a11481006000526004601cfd5b846115865763ea553b346000526004601cfd5b8560005281600101549250823314863314176115b4576030600c20546115b457634b6e7f186000526004601cfd5b82156115c257600082600101555b85851818905550601c600c8181208054600019019055600084905220805460010163ffffffff81166115fc576301336cea6000526004601cfd5b90558082847fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a45b505050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60008060008661168a876131d7565b61169b611696896131d7565b613222565b6116ac6116a78a6131d7565b613312565b6040516020016116bf949392919061511e565b60408051601f19818403018152908290526004805463040a7bb160e41b84529193506001600160a01b03909116916340a7bb1091611707918c91309187918c918c91016151be565b6040805180830381865afa158015611723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117479190615212565b92509250509550959350505050565b61ffff831660009081526005602052604081208054829190611777906150d4565b80601f01602080910402602001604051908101604052809291908181526020018280546117a3906150d4565b80156117f05780601f106117c5576101008083540402835291602001916117f0565b820191906000526020600020905b8154815290600101906020018083116117d357829003601f168201915b50505050509050838360405161180792919061510e565b60405180910390208180519060200120149150505b9392505050565b61182e838383611515565b813b1561162757611627838383604051806020016040528060008152506133c3565b61185a3382613447565b6118c05760405162461bcd60e51b815260206004820152603160248201527f596f75417265486572653a206275726e2063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606482015260840161113b565b6118c9816134b3565b50565b6118d461311b565b600480546040516342d65a8d60e01b81526001600160a01b03909116916342d65a8d91611907918791879187910161525f565b600060405180830381600087803b15801561192157600080fd5b505af11580156112ef573d6000803e3d6000fd5b601154600160a01b900460ff161561195f5760405162461bcd60e51b815260040161113b9061527d565b6011546001600160a01b031633146119a95760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f434c41494d41424c4560981b604482015260640161113b565b6119b2466134be565b6011805460ff60a01b1916600160a01b1790556119cf33466134e9565b565b6112ef8787876119e0886131d7565b6119ec6116968a6131d7565b6119f86116a78b6131d7565b898989613597565b611a0861311b565b611627838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250613771915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6060611a8d82613831565b611aa95760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b031663b10c9af583611ac481613855565b6040518363ffffffff1660e01b8152600401611ae19291906152c8565b600060405180830381865afa158015611afe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113329190810190615311565b6000818152673ec412a9852d173d60c11b601c526020902081018101546001600160a01b031680611b5f5763ceea21b66000526004601cfd5b919050565b333014611bc25760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b606482015260840161113b565b611c388686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506139cd92505050565b505050505050565b601154600160a01b900460ff1615611c6a5760405162461bcd60e51b815260040161113b9061527d565b4260105410611caa5760405162461bcd60e51b815260206004820152600c60248201526b4e4f545f4d494e5441424c4560a01b604482015260640161113b565b600f543414611ce35760405162461bcd60e51b8152602060048201526005602482015264505249434560d81b604482015260640161113b565b611cec466134be565b6011805460ff60a01b1916600160a01b1790556118c981466134e9565b611d1161311b565b828114611d605760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20696e76616c696420696e707574206c656e6774680000000000604482015260640161113b565b60005b8381101561139f57828282818110611d7d57611d7d615359565b9050602002810190611d8f919061536f565b30604051602001611da2939291906153b5565b60405160208183030381529060405260056000878785818110611dc757611dc7615359565b9050602002016020810190611ddc9190614662565b61ffff168152602081019190915260400160002090611dfb9082615421565b5080611e06816154f6565b915050611d63565b600081611e2357638f4eb6046000526004601cfd5b673ec412a9852d173d60c11b601c528160005263ffffffff601c600c2054169050919050565b611e5161311b565b6119cf6000613b2e565b60056020526000908152604090208054611e74906150d4565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea0906150d4565b8015611eed5780601f10611ec257610100808354040283529160200191611eed565b820191906000526020600020905b815481529060010190602001808311611ed057829003601f168201915b505050505081565b611efd61311b565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b611f2761311b565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114611f74576040519150601f19603f3d011682016040523d82523d6000602084013e611f79565b606091505b50509050806113f057600080fd5b6000611f9282613831565b15611fa05761133282611b26565b506000919050565b611fb061311b565b828114611fff5760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20696e76616c696420696e707574206c656e6774680000000000604482015260640161113b565b60005b8381101561139f5782828281811061201c5761201c615359565b905060200281019061202e919061536f565b6005600088888681811061204457612044615359565b90506020020160208101906120599190614662565b61ffff16815260208101919091526040016000209161207991908361550f565b5080612084816154f6565b915050612002565b61209461311b565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6120be613b6c565b80516020808301919091206000818152600e90925260409091206002015460ff1661211f5760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b604482015260640161113b565b6000806000848060200190518101906121389190615649565b6000888152600e602052604081208054600190910154949850929650909450925061217b9161ffff8216916201000090046001600160a01b031690878787613bc5565b6000868152600e602052604090206001015490915081116121f05760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b606482015260840161113b565b83518103612267576000858152600e602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba2339061225a9087815260200190565b60405180910390a1612376565b6040518060800160405280600e600088815260200190815260200160002060000160009054906101000a900461ffff1661ffff168152602001600e600088815260200190815260200160002060000160029054906101000a90046001600160a01b03166001600160a01b0316815260200182815260200160011515815250600e600087815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816001015560608201518160020160006101000a81548160ff0219169083151502179055509050505b50505050506118c96001600a55565b61238d61311b565b601154600160a01b900460ff166123d35760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b604482015260640161113b565b4660009081526002602052604081205490036123f2576123f2466134be565b6118c981466134e9565b61240461311b565b600f55565b61241161311b565b601055565b61241e61311b565b600081116124795760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b606482015260840161113b565b61ffff82166000818152600c6020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff81166000908152600560205260408120805460609291906124f0906150d4565b80601f016020809104026020016040519081016040528092919081815260200182805461251c906150d4565b80156125695780601f1061253e57610100808354040283529160200191612569565b820191906000526020600020905b81548152906001019060200180831161254c57829003601f168201915b5050505050905080516000036125c15760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f7264000000604482015260640161113b565b61181c6000601483516125d4919061578f565b839190613c50565b6060600082516001600160401b038111156125f9576125f9614761565b604051908082528060200260200182016040528015612622578160200160208202803683370190505b50905060005b835181101561268f5761265384828151811061264657612646615359565b6020026020010151611f87565b82828151811061266557612665615359565b6001600160a01b039092166020928302919091019091015280612687816154f6565b915050612628565b5092915050565b801515905081601c52670a5a2e7a0000000060085233600052806030600c2055806000528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206000a35050565b6126f461311b565b818130604051602001612709939291906153b5565b60408051601f1981840301815291815261ffff85166000908152600560205220906127349082615421565b50505050565b6112ef8787878761274a89613222565b6119f88a613312565b61275b61311b565b601154600160a81b900460ff16156127855760405162461bcd60e51b815260040161113b9061527d565b466001148061279657504662aa36a7145b806127a2575046617a69145b6127dc5760405162461bcd60e51b815260206004820152600b60248201526a1393d517d350525393915560aa1b604482015260640161113b565b6011805460ff60a81b1916600160a81b1790556127fa610fff6134be565b61280662ffffff6134be565b612814640fffffffff6134be565b61282081610fff6134e9565b61282d8162ffffff6134e9565b6118c981640fffffffff6134e9565b612847858585611515565b833b1561139f5761139f85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133c392505050565b61289861311b565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611489565b6012546040516303c0bff160e41b81526060916001600160a01b031690633c0bff109061291990869086906004016152c8565b600060405180830381865afa158015612936573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261181c9190810190615311565b61296661311b565b601154600160a01b900460ff1615611ce35760405162461bcd60e51b815260040161113b9061527d565b606061133282613855565b60606129a682613831565b6129c25760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b0316638c63e25b836129dd81613855565b600086815260036020526040908190205490516001600160e01b031960e086901b168152611ae1939291906004016157a2565b612a1861311b565b600480546040516332fb62e760e21b81526001600160a01b039091169163cbed8b9c91612a4f9189918991899189918991016157cb565b600060405180830381600087803b158015612a6957600080fd5b505af1158015612a7d573d6000803e3d6000fd5b505050505050505050565b612a9061311b565b60008111612aec5760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b606482015260840161113b565b61ffff82166000818152600d6020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb91016124c1565b6060612b4382613831565b612b5f5760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b0316633c0bff1083611ac481613855565b61ffff86166000908152600960205260408082209051612b9d908890889061510e565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080612c1d5760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b606482015260840161113b565b808383604051612c2e92919061510e565b604051809103902014612c8d5760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b606482015260840161113b565b61ffff87166000908152600960205260408082209051612cb0908990899061510e565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612d48918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506139cd92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612d7f9594939291906157f9565b60405180910390a150505050505050565b612d9861311b565b6004546001600160a01b031615612df15760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206c7a456e64706f696e7420616c726561647920736574000000604482015260640161113b565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b612e1b61311b565b61ffff92831660009081526006602090815260408083209490951682529290925291902055565b6060600082516001600160401b03811115612e5f57612e5f614761565b604051908082528060200260200182016040528015612e9257816020015b6060815260200190600190039081612e7d5790505b50905060005b835181101561268f57612ec3848281518110612eb657612eb6615359565b6020026020010151613855565b828281518110612ed557612ed5615359565b60200260200101819052508080612eeb906154f6565b915050612e98565b6060600080600080612f04866125dc565b601054601154600f54929991985060ff600160a01b82041697509195506001600160a01b039091169350915050565b60125460405163b10c9af560e01b81526060916001600160a01b03169063b10c9af59061291990869086906004016152c8565b612f6e61311b565b61ffff8316600090815260056020526040902061273482848361550f565b612f9461311b565b63389a75e1600c52806000526020600c208054421115612fbc57636f5e88186000526004601cfd5b600090556118c981613b2e565b60008060008686612fd988613222565b6116ac89613312565b612fea61311b565b8060601b61300057637448fbae6000526004601cfd5b6118c981613b2e565b60048054604051633d7b2f6f60e21b815261ffff808816938201939093529185166024830152306044830152606482018390526060916001600160a01b039091169063f5ecbdbc90608401600060405180830381865afa158015613071573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130999190810190615834565b95945050505050565b6000806131055a60966366ad5c8a60e01b898989896040516024016130ca9493929190615868565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190613d5d565b9150915081611c3857611c388686868685613de7565b638b78c6d8195433146119cf576382b429006000526004601cfd5b60001960601c828116925083811693508160005283673ec412a9852d173d60c11b17601c526020600020820182018054821691508161317d5763ceea21b66000526004601cfd5b8185148515176131a357816000526030600c20546131a357634b6e7f186000526004601cfd5b6001018390558183827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600038a450505050565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061321157613211615359565b602090810291909101015292915050565b6060600082516001600160401b0381111561323f5761323f614761565b60405190808252806020026020018201604052801561327857816020015b6132656144b3565b81526020019060019003908161325d5790505b50905060005b835181101561268f576002600085838151811061329d5761329d615359565b60209081029190910181015182528101919091526040908101600020815160808101928390529160049082845b8154815260200190600101908083116132ca5750505050508282815181106132f4576132f4615359565b6020026020010181905250808061330a906154f6565b91505061327e565b6060600082516001600160401b0381111561332f5761332f614761565b604051908082528060200260200182016040528015613358578160200160208202803683370190505b50905060005b835181101561268f576003600085838151811061337d5761337d615359565b60200260200101518152602001908152602001600020548282815181106133a6576133a6615359565b6020908102919091010152806133bb816154f6565b91505061335e565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a0840152801561340a578060c08401826020870160045afa505b60208360a48301601c860160008a5af161342d573d1561342d573d6000843e3d83fd5b508060e01b825114611c385763d1a57ed66000526004601cfd5b60008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c5260209091208201820180549193600192168061348c5763ceea21b66000526004601cfd5b8085146134ab57806000526030600c20546134ab578160010154851492505b505092915050565b6118c9600082613e84565b4660009081526001602081815260408084205494845260028252808420949094556003905291902055565b6001600160a01b0390911690816135085763ea553b346000526004601cfd5b80600052673ec412a9852d173d60c11b601c5260206000208101810180548060601b1561353d5763c991cbb16000526004601cfd5b831790556000829052601c600c20805460010163ffffffff8116613569576301336cea6000526004601cfd5b9055808260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8138a45050565b60008651116135de5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b604482015260640161113b565b855160011480613602575061ffff88166000908152600c6020526040902054865111155b6136595760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b606482015260840161113b565b60005b865181101561369c5761368a8a8a8a8a858151811061367d5761367d615359565b6020026020010151613f52565b80613694816154f6565b91505061365c565b506000878787876040516020016136b6949392919061511e565b60405160208183030381529060405290506136fb896001848a51600d60008f61ffff1661ffff168152602001908152602001600020546136f691906158a6565b614042565b613709898286868634614129565b8760405161371791906158bd565b60405180910390208a6001600160a01b03168a61ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a8a60405161375d9190614eb5565b60405180910390a450505050505050505050565b61010082518261378191906158d9565b11156137a057604051630fb9d71f60e11b815260040160405180910390fd5b60005b8251811015611627578281815181106137be576137be615359565b602002602001015160008083856137d591906158d9565b81526020810191909152604001600020556137f081836158d9565b6001600085848151811061380657613806615359565b60200260200101518152602001908152602001600020819055508061382a906154f6565b90506137a3565b6000818152673ec412a9852d173d60c11b601c52602090208101015460601b151590565b600081815260036020526040812054606091608082116138755781613878565b60805b90506000816001600160401b0381111561389457613894614761565b6040519080825280602002602001820160405280156138bd578160200160208202803683370190505b50600086815260026020526040808220815160808101928390529394509192919060049082845b8154815260200190600101908083116138e4575050505050905060005b82518110156139c257600060808261391a60018961578f565b613924919061578f565b61392e9190615902565b9050600061393d602083615916565b9050600061394c602084615902565b6139579060086158a6565b905060008186846004811061396e5761396e615359565b6020020151901c60ff1690506000808281526020019081526020016000205487868151811061399f5761399f615359565b6020026020010181815250505050505080806139ba906154f6565b915050613901565b509095945050505050565b600080600080848060200190518101906139e79190615649565b6014840151939750919550935091506000613a068a8383888888613bc5565b90508451811015613ada5786516020808901919091206040805160808101825261ffff808f1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600e909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790613ad09083908b9061592a565b60405180910390a1505b816001600160a01b031689604051613af291906158bd565b60405180910390208b61ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d9902658860405161375d9190614eb5565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6002600a5403613bbe5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161113b565b6002600a55565b6000845b8451811015613c4557600b545a10613c4557613c338888878481518110613bf257613bf2615359565b6020026020010151878581518110613c0c57613c0c615359565b6020026020010151878681518110613c2657613c26615359565b60200260200101516142b1565b80613c3d816154f6565b915050613bc9565b979650505050505050565b606081613c5e81601f6158d9565b1015613c9d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161113b565b613ca782846158d9565b84511015613ceb5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161113b565b606082158015613d0a5760405191506000825260208201604052613d54565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613d43578051835260209283019201613d2b565b5050858452601f01601f1916604052505b50949350505050565b6000606060008060008661ffff166001600160401b03811115613d8257613d82614761565b6040519080825280601f01601f191660200182016040528015613dac576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115613dce578692505b828152826000602083013e909890975095505050505050565b8180519060200120600960008761ffff1661ffff16815260200190815260200160002085604051613e1891906158bd565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90613e759087908790879087908790615943565b60405180910390a15050505050565b6000613e8f82611b26565b90505060008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c526020909120820182018054919382169182613ed65763ceea21b66000526004601cfd5b82600052816001015480861484871417861517613f05576030600c2054613f0557634b6e7f186000526004601cfd5b8015613f1357600083600101555b5082189055601c600c208054600019019055816000827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8238a4505050565b613f5c3382613447565b613fc25760405162461bcd60e51b815260206004820152603160248201527f596f75417265486572653a2073656e642063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606482015260840161113b565b836001600160a01b0316613fd582611b26565b6001600160a01b0316146140395760405162461bcd60e51b815260206004820152602560248201527f596f75417265486572653a2073656e642066726f6d20696e636f72726563742060448201526437bbb732b960d91b606482015260840161113b565b612734816134b3565b600061404d836142d9565b61ffff80871660009081526006602090815260408083209389168352929052908120549192508190036140805750620249f05b600081116140d05760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f7420736574000000000000604482015260640161113b565b6140da83826158d9565b821015611c385760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f770000000000604482015260640161113b565b61ffff861660009081526005602052604081208054614147906150d4565b80601f0160208091040260200160405190810160405280929190818152602001828054614173906150d4565b80156141c05780601f10614195576101008083540402835291602001916141c0565b820191906000526020600020905b8154815290600101906020018083116141a357829003601f168201915b5050505050905080516000036142315760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b606482015260840161113b565b61423c878751614335565b6004805460405162c5803160e81b81526001600160a01b039091169163c5803100918591614276918c9187918d918d918d918d9101615995565b6000604051808303818588803b15801561428f57600080fd5b505af11580156142a3573d6000803e3d6000fd5b505050505050505050505050565b6142ba83613831565b156142c457600080fd5b6142cf8383836143a6565b61139f84846134e9565b600060228251101561432d5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d7300000000604482015260640161113b565b506022015190565b61ffff82166000908152600760205260408120549081900361435657506127105b808211156116275760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c61726765604482015260640161113b565b60006143b3608083615902565b905060006143c2602083615916565b905060006143d1602084615902565b6143dc9060086158a6565b905060ff811b196000818785600481106143f8576143f8615359565b6020020151169050826001600046815260200190815260200160002054901b811787856004811061442b5761442b615359565b602002015260005b600481101561448b5787816004811061444e5761444e615359565b6020020151600260008b8152602001908152602001600020826004811061447757614477615359565b015580614483816154f6565b915050614433565b506144978660016158d9565b6000988952600360205260409098209790975550505050505050565b60405180608001604052806004906020820280368337509192915050565b803561ffff81168114611b5f57600080fd5b60008083601f8401126144f557600080fd5b5081356001600160401b0381111561450c57600080fd5b60208301915083602082850101111561452457600080fd5b9250929050565b80356001600160401b0381168114611b5f57600080fd5b6000806000806000806080878903121561455b57600080fd5b614564876144d1565b955060208701356001600160401b038082111561458057600080fd5b61458c8a838b016144e3565b90975095508591506145a060408a0161452b565b945060608901359150808211156145b657600080fd5b506145c389828a016144e3565b979a9699509497509295939492505050565b6000602082840312156145e757600080fd5b81356001600160e01b03198116811461181c57600080fd5b60005b8381101561461a578181015183820152602001614602565b50506000910152565b6000815180845261463b8160208601602086016145ff565b601f01601f19169290920160200192915050565b60208152600061181c6020830184614623565b60006020828403121561467457600080fd5b61181c826144d1565b60006020828403121561468f57600080fd5b5035919050565b6001600160a01b03811681146118c957600080fd5b8035611b5f81614696565b600080604083850312156146c957600080fd5b82356146d481614696565b946020939093013593505050565b600080604083850312156146f557600080fd5b6146d4836144d1565b6000806040838503121561471157600080fd5b50508035926020909101359150565b60008060006060848603121561473557600080fd5b833561474081614696565b9250602084013561475081614696565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171561479957614799614761565b60405290565b604051601f8201601f191681016001600160401b03811182821017156147c7576147c7614761565b604052919050565b60006001600160401b038211156147e8576147e8614761565b50601f01601f191660200190565b600082601f83011261480757600080fd5b813561481a614815826147cf565b61479f565b81815284602083860101111561482f57600080fd5b816020850160208301376000918101602001919091529392505050565b80358015158114611b5f57600080fd5b600080600080600060a0868803121561487457600080fd5b61487d866144d1565b945060208601356001600160401b038082111561489957600080fd5b6148a589838a016147f6565b9550604088013594506148ba6060890161484c565b935060808801359150808211156148d057600080fd5b506148dd888289016147f6565b9150509295509295909350565b6000806000604084860312156148ff57600080fd5b614908846144d1565b925060208401356001600160401b0381111561492357600080fd5b61492f868287016144e3565b9497909650939450505050565b600080600080600080600060e0888a03121561495757600080fd5b873561496281614696565b9650614970602089016144d1565b955060408801356001600160401b038082111561498c57600080fd5b6149988b838c016147f6565b965060608a0135955060808a013591506149b182614696565b90935060a0890135906149c382614696565b90925060c089013590808211156149d957600080fd5b506149e68a828b016147f6565b91505092959891949750929550565b60008083601f840112614a0757600080fd5b5081356001600160401b03811115614a1e57600080fd5b6020830191508360208260051b850101111561452457600080fd5b600080600060408486031215614a4e57600080fd5b83356001600160401b03811115614a6457600080fd5b614a70868287016149f5565b909790965060209590950135949350505050565b600080600060608486031215614a9957600080fd5b614aa2846144d1565b925060208401356001600160401b03811115614abd57600080fd5b614ac9868287016147f6565b925050614ad86040850161452b565b90509250925092565b600060208284031215614af357600080fd5b813561181c81614696565b60008060008060408587031215614b1457600080fd5b84356001600160401b0380821115614b2b57600080fd5b614b37888389016149f5565b90965094506020870135915080821115614b5057600080fd5b50614b5d878288016149f5565b95989497509550505050565b60008060408385031215614b7c57600080fd5b614b85836144d1565b9150614b93602084016144d1565b90509250929050565b600060208284031215614bae57600080fd5b81356001600160401b03811115614bc457600080fd5b614bd0848285016147f6565b949350505050565b60006001600160401b03821115614bf157614bf1614761565b5060051b60200190565b600082601f830112614c0c57600080fd5b81356020614c1c61481583614bd8565b82815260059290921b84018101918181019086841115614c3b57600080fd5b8286015b84811015614c565780358352918301918301614c3f565b509695505050505050565b600060208284031215614c7357600080fd5b81356001600160401b03811115614c8957600080fd5b614bd084828501614bfb565b600081518084526020808501945080840160005b83811015614cce5781516001600160a01b031687529582019590820190600101614ca9565b509495945050505050565b60208152600061181c6020830184614c95565b60008060408385031215614cff57600080fd5b8235614d0a81614696565b9150614b936020840161484c565b600080600080600080600060e0888a031215614d3357600080fd5b8735614d3e81614696565b9650614d4c602089016144d1565b955060408801356001600160401b0380821115614d6857600080fd5b614d748b838c016147f6565b965060608a0135915080821115614d8a57600080fd5b614d968b838c01614bfb565b955060808a01359150614da882614696565b819450614db760a08b016146ab565b935060c08a01359150808211156149d957600080fd5b600080600080600060808688031215614de557600080fd5b8535614df081614696565b94506020860135614e0081614696565b93506040860135925060608601356001600160401b03811115614e2257600080fd5b614e2e888289016144e3565b969995985093965092949392505050565b60008060408385031215614e5257600080fd5b8235915060208301356001600160401b03811115614e6f57600080fd5b614e7b85828601614bfb565b9150509250929050565b600081518084526020808501945080840160005b83811015614cce57815187529582019590820190600101614e99565b60208152600061181c6020830184614e85565b600080600080600060808688031215614ee057600080fd5b614ee9866144d1565b9450614e00602087016144d1565b600080600060608486031215614f0c57600080fd5b614f15846144d1565b9250614f23602085016144d1565b9150604084013590509250925092565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614f8857603f19888603018452614f76858351614e85565b94509285019290850190600101614f5a565b5092979650505050505050565b60a081526000614fa860a0830188614c95565b602083019690965250921515604084015260608301919091526001600160a01b0316608090910152919050565b60008060408385031215614fe857600080fd5b8235614ff381614696565b9150602083013561500381614696565b809150509250929050565b600080600080600060a0868803121561502657600080fd5b61502f866144d1565b945060208601356001600160401b038082111561504b57600080fd5b61505789838a016147f6565b9550604088013591508082111561506d57600080fd5b61507989838a01614bfb565b94506148ba6060890161484c565b6000806000806080858703121561509d57600080fd5b6150a6856144d1565b93506150b4602086016144d1565b925060408501356150c481614696565b9396929550929360600135925050565b600181811c908216806150e857607f821691505b60208210810361510857634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b6000608080835261513181840188614623565b6020848203818601526151448289614e85565b858103604087015287518082528289019350908201906000805b8281101561519b57855184835b60048110156151885782518252918701919087019060010161516b565b505050948401949286019260010161515e565b50505085810360608701526151b08188614e85565b9a9950505050505050505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906151ec90830186614623565b841515606084015282810360808401526152068185614623565b98975050505050505050565b6000806040838503121561522557600080fd5b505080516020909101519092909150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff84168152604060208201526000613099604083018486615236565b6020808252600e908201526d1053149150511657d3525395115160921b604082015260600190565b6020808252600990820152681393d517d193d5539160ba1b604082015260600190565b828152604060208201526000614bd06040830184614e85565b60006152ef614815846147cf565b905082815283838301111561530357600080fd5b61181c8360208301846145ff565b60006020828403121561532357600080fd5b81516001600160401b0381111561533957600080fd5b8201601f8101841361534a57600080fd5b614bd0848251602084016152e1565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261538657600080fd5b8301803591506001600160401b038211156153a057600080fd5b60200191503681900382131561452457600080fd5b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f82111561162757600081815260208120601f850160051c810160208610156154025750805b601f850160051c820191505b81811015611c385782815560010161540e565b81516001600160401b0381111561543a5761543a614761565b61544e8161544884546150d4565b846153db565b602080601f831160018114615483576000841561546b5750858301515b600019600386901b1c1916600185901b178555611c38565b600085815260208120601f198616915b828110156154b257888601518255948401946001909101908401615493565b50858210156154d05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600060018201615508576155086154e0565b5060010190565b6001600160401b0383111561552657615526614761565b61553a8361553483546150d4565b836153db565b6000601f84116001811461556e57600085156155565750838201355b600019600387901b1c1916600186901b17835561139f565b600083815260209020601f19861690835b8281101561559f578685013582556020948501946001909201910161557f565b50868210156155bc5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b600082601f8301126155df57600080fd5b61181c838351602085016152e1565b600082601f8301126155ff57600080fd5b8151602061560f61481583614bd8565b82815260059290921b8401810191818101908684111561562e57600080fd5b8286015b84811015614c565780518352918301918301615632565b600080600080608080868803121561566057600080fd5b85516001600160401b038082111561567757600080fd5b61568389838a016155ce565b965060209150818801518181111561569a57600080fd5b6156a68a828b016155ee565b9650506040880151818111156156bb57600080fd5b8801601f81018a136156cc57600080fd5b80516156da61481582614bd8565b81815260079190911b8201840190848101908c8311156156f957600080fd5b928501925b8284101561575b578c601f8501126157165760008081fd5b61571e614777565b808886018f8111156157305760008081fd5b865b818110156157495780518452928901928901615732565b505083525092860192908501906156fe565b60608c015190985095505050508083111561577557600080fd5b5050615783878288016155ee565b91505092959194509250565b81810381811115611332576113326154e0565b8381526060602082015260006157bb6060830185614e85565b9050826040830152949350505050565b600061ffff808816835280871660208401525084604083015260806060830152613c45608083018486615236565b61ffff86168152608060208201526000615817608083018688615236565b6001600160401b0394909416604083015250606001529392505050565b60006020828403121561584657600080fd5b81516001600160401b0381111561585c57600080fd5b614bd0848285016155ce565b61ffff851681526080602082015260006158856080830186614623565b6001600160401b03851660408401528281036060840152613c458185614623565b8082028115828204841417611332576113326154e0565b600082516158cf8184602087016145ff565b9190910192915050565b80820180821115611332576113326154e0565b634e487b7160e01b600052601260045260246000fd5b600082615911576159116158ec565b500690565b600082615925576159256158ec565b500490565b828152604060208201526000614bd06040830184614623565b61ffff8616815260a06020820152600061596060a0830187614623565b6001600160401b038616604084015282810360608401526159818186614623565b905082810360808401526152068185614623565b61ffff8716815260c0602082015260006159b260c0830188614623565b82810360408401526159c48188614623565b6001600160a01b0387811660608601528616608085015283810360a085015290506159ef8185614623565b999850505050505050505056fea2646970667358221220ac8b222083a89263f1e1a3d7e7f7909d91b30a156ddb36f7a1b9d1e1cd9e2ab464736f6c63430008130033

Deployed Bytecode

0x6080604052600436106104e05760003560e01c80638cfd8f5c11610281578063bb0946db1161015a578063e18abcd5116100cc578063f235364111610085578063f235364114611005578063f2fde38b14611025578063f5ecbdbc14611038578063fa25f9b614611058578063fee81cf414611085578063ff6acee9146110b857600080fd5b8063e18abcd514610f1e578063e5aa1b2d14610f4b578063e9726bcb14610f7c578063e985e9c514610f9c578063eb8d72b714610fd2578063f04e283e14610ff257600080fd5b8063cbed8b9c1161011e578063cbed8b9c14610e6b578063d12473a514610e8b578063d12a4c9814610eab578063d1deba1f14610ecb578063d9331a1114610ede578063df2a5b3b14610efe57600080fd5b8063bb0946db14610dc8578063bb69985214610de8578063c446183414610e08578063c8691b2a14610e1e578063c87b56dd14610e4b57600080fd5b80639f38369a116101f3578063ab3ffb93116101b7578063ab3ffb9314610d1a578063ad5343c314610d2d578063af3fb21c14610d4d578063b353aaa714610d75578063b88d4fde14610d95578063baf3292d14610da857600080fd5b80639f38369a14610c775780639fd0bb9c14610c97578063a035b1fe14610cc4578063a22cb46514610cda578063a6c3d16514610cfa57600080fd5b806391e4bac81161024557806391e4bac814610b8a578063950c8a7414610baa57806395d89b4114610bca5780639a4526ed14610bfd5780639e8c3ec614610c2a5780639ea5d6b114610c5757600080fd5b80638cfd8f5c14610ad95780638da5cb5b14610b115780638ffa1f2a14610b2a57806390ca791914610b4a57806391b7f5ed14610b6a57600080fd5b80634ac3f4ff116103be57806368bbe82111610330578063754babe6116102e9578063754babe614610a19578063756af45f14610a39578063770e6e3214610a595780637f81be6914610a7957806380e1655214610a995780638415d21314610ab957600080fd5b806368bbe821146109875780636a6278421461099e5780636f202f2a146109b157806370a08231146109d1578063715018a6146109f15780637533d788146109f957600080fd5b806354ce6d941161038257806354ce6d94146108b057806354d1f13d146108d05780635b8c41e6146108d85780635ca2ddf1146109275780636352211e1461094757806366ad5c8a1461096757600080fd5b80634ac3f4ff146108315780634bf365df1461085e5780634e71d92d146108745780634f02c4201461087c578063519056361461089d57600080fd5b8063173db2e5116104575780633d8b38f61161041b5780633d8b38f61461077b5780633f1f4fa41461079b57806342842e0e146107c857806342966c68146107db57806342d65a8d146107fb578063482881901461081b57600080fd5b8063173db2e51461068857806322a3ecf9146106a857806323b872dd1461072b578063256929621461073e5780632a205e3d1461074657600080fd5b8063095ea7b3116104a9578063095ea7b3146105d25780630b4cad4c146105e55780630df374831461060557806310ddb13714610625578063143a555c146106455780631446644b1461067357600080fd5b80621d3567146104e557806301ffc9a71461050757806306fdde031461053c57806307e0db171461057a578063081812fc1461059a575b600080fd5b3480156104f157600080fd5b50610505610500366004614542565b6110e5565b005b34801561051357600080fd5b506105276105223660046145d5565b6112f8565b60405190151581526020015b60405180910390f35b34801561054857600080fd5b5060408051808201909152600c81526b596f7520417265204865726560a01b60208201525b604051610533919061464f565b34801561058657600080fd5b50610505610595366004614662565b611338565b3480156105a657600080fd5b506105ba6105b536600461467d565b6113a6565b6040516001600160a01b039091168152602001610533565b6105056105e03660046146b6565b6113e5565b3480156105f157600080fd5b5061050561060036600461467d565b6113f4565b34801561061157600080fd5b506105056106203660046146e2565b611494565b34801561063157600080fd5b50610505610640366004614662565b6114b3565b34801561065157600080fd5b506106656106603660046146fe565b6114f0565b604051908152602001610533565b34801561067f57600080fd5b50610665608081565b34801561069457600080fd5b506012546105ba906001600160a01b031681565b3480156106b457600080fd5b506106fc6106c336600461467d565b600e6020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b0390931660208501529183015215156060820152608001610533565b610505610739366004614720565b611515565b61050561162c565b34801561075257600080fd5b5061076661076136600461485c565b61167b565b60408051928352602083019190915201610533565b34801561078757600080fd5b506105276107963660046148ea565b611756565b3480156107a757600080fd5b506106656107b6366004614662565b60076020526000908152604090205481565b6105056107d6366004614720565b611823565b3480156107e757600080fd5b506105056107f636600461467d565b611850565b34801561080757600080fd5b506105056108163660046148ea565b6118cc565b34801561082757600080fd5b50610665600b5481565b34801561083d57600080fd5b5061066561084c366004614662565b600c6020526000908152604090205481565b34801561086a57600080fd5b5061066560105481565b610505611935565b34801561088857600080fd5b5060115461052790600160a01b900460ff1681565b6105056108ab36600461493c565b6119d1565b3480156108bc57600080fd5b506105056108cb366004614a39565b611a00565b610505611a46565b3480156108e457600080fd5b506106656108f3366004614a84565b6009602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561093357600080fd5b5061056d61094236600461467d565b611a82565b34801561095357600080fd5b506105ba61096236600461467d565b611b26565b34801561097357600080fd5b50610505610982366004614542565b611b64565b34801561099357600080fd5b50610665620249f081565b6105056109ac366004614ae1565b611c40565b3480156109bd57600080fd5b506105056109cc366004614afe565b611d09565b3480156109dd57600080fd5b506106656109ec366004614ae1565b611e0e565b610505611e49565b348015610a0557600080fd5b5061056d610a14366004614662565b611e5b565b348015610a2557600080fd5b50610505610a34366004614ae1565b611ef5565b348015610a4557600080fd5b50610505610a54366004614ae1565b611f1f565b348015610a6557600080fd5b506011546105ba906001600160a01b031681565b348015610a8557600080fd5b506105ba610a9436600461467d565b611f87565b348015610aa557600080fd5b50610505610ab4366004614afe565b611fa8565b348015610ac557600080fd5b50610505610ad4366004614ae1565b61208c565b348015610ae557600080fd5b50610665610af4366004614b69565b600660209081526000928352604080842090915290825290205481565b348015610b1d57600080fd5b50638b78c6d819546105ba565b348015610b3657600080fd5b50610505610b45366004614b9c565b6120b6565b348015610b5657600080fd5b50610505610b65366004614ae1565b612385565b348015610b7657600080fd5b50610505610b8536600461467d565b6123fc565b348015610b9657600080fd5b50610505610ba536600461467d565b612409565b348015610bb657600080fd5b506008546105ba906001600160a01b031681565b348015610bd657600080fd5b5060408051808201909152600a815269594f554152454845524560b01b602082015261056d565b348015610c0957600080fd5b50610665610c1836600461467d565b60016020526000908152604090205481565b348015610c3657600080fd5b50610665610c4536600461467d565b60006020819052908152604090205481565b348015610c6357600080fd5b50610505610c723660046146e2565b612416565b348015610c8357600080fd5b5061056d610c92366004614662565b6124cd565b348015610ca357600080fd5b50610cb7610cb2366004614c61565b6125dc565b6040516105339190614cd9565b348015610cd057600080fd5b50610665600f5481565b348015610ce657600080fd5b50610505610cf5366004614cec565b612696565b348015610d0657600080fd5b50610505610d153660046148ea565b6126ec565b610505610d28366004614d18565b61273a565b348015610d3957600080fd5b50610505610d48366004614ae1565b612753565b348015610d5957600080fd5b50610d62600181565b60405161ffff9091168152602001610533565b348015610d8157600080fd5b506004546105ba906001600160a01b031681565b610505610da3366004614dcd565b61283c565b348015610db457600080fd5b50610505610dc3366004614ae1565b612890565b348015610dd457600080fd5b5061056d610de3366004614e3f565b6128e6565b348015610df457600080fd5b50610505610e03366004614ae1565b61295e565b348015610e1457600080fd5b5061066561271081565b348015610e2a57600080fd5b50610e3e610e3936600461467d565b612990565b6040516105339190614eb5565b348015610e5757600080fd5b5061056d610e6636600461467d565b61299b565b348015610e7757600080fd5b50610505610e86366004614ec8565b612a10565b348015610e9757600080fd5b50610505610ea63660046146e2565b612a88565b348015610eb757600080fd5b5061056d610ec636600461467d565b612b38565b610505610ed9366004614542565b612b7a565b348015610eea57600080fd5b50610505610ef9366004614ae1565b612d90565b348015610f0a57600080fd5b50610505610f19366004614ef7565b612e13565b348015610f2a57600080fd5b50610f3e610f39366004614c61565b612e42565b6040516105339190614f33565b348015610f5757600080fd5b50610f6b610f66366004614c61565b612ef3565b604051610533959493929190614f95565b348015610f8857600080fd5b5061056d610f97366004614e3f565b612f33565b348015610fa857600080fd5b50610527610fb7366004614fd5565b601c52670a5a2e7a000000006008526000526030600c205490565b348015610fde57600080fd5b50610505610fed3660046148ea565b612f66565b610505611000366004614ae1565b612f8c565b34801561101157600080fd5b5061076661102036600461500e565b612fc9565b610505611033366004614ae1565b612fe2565b34801561104457600080fd5b5061056d611053366004615087565b613009565b34801561106457600080fd5b50610665611073366004614662565b600d6020526000908152604090205481565b34801561109157600080fd5b506106656110a0366004614ae1565b63389a75e1600c908152600091909152602090205490565b3480156110c457600080fd5b506106656110d336600461467d565b60036020526000908152604090205481565b6004546001600160a01b031633146111445760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526005602052604081208054611162906150d4565b80601f016020809104026020016040519081016040528092919081815260200182805461118e906150d4565b80156111db5780601f106111b0576101008083540402835291602001916111db565b820191906000526020600020905b8154815290600101906020018083116111be57829003601f168201915b505050505090508051868690501480156111f6575060008151115b801561121e575080516020820120604051611214908890889061510e565b6040518091039020145b6112795760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b606482015260840161113b565b6112ef8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506130a292505050565b50505050505050565b60006001600160e01b0319821615806113325750611332826301ffc9a760e09190911c9081146380ac58cd821417635b5e139f9091141790565b92915050565b61134061311b565b600480546040516307e0db1760e01b815261ffff8416928101929092526001600160a01b0316906307e0db17906024015b600060405180830381600087803b15801561138b57600080fd5b505af115801561139f573d6000803e3d6000fd5b5050505050565b600081600052673ec412a9852d173d60c11b601c52602060002082018201805460601b6113db5763ceea21b66000526004601cfd5b6001015492915050565b6113f0338383613136565b5050565b6113fc61311b565b600081116114585760405162461bcd60e51b8152602060048201526024808201527f6d696e476173546f5472616e73666572416e6453746f7265206d7573742062656044820152630203e20360e41b606482015260840161113b565b600b8190556040518181527ffebbc4f8bb9ec2313950c718d43123124b15778efda4c1f1d529de2995b4f34d906020015b60405180910390a150565b61149c61311b565b61ffff909116600090815260076020526040902055565b6114bb61311b565b600480546040516310ddb13760e01b815261ffff8416928101929092526001600160a01b0316906310ddb13790602401611371565b6002602052816000526040600020816004811061150c57600080fd5b01549150829050565b6000818152673ec412a9852d173d60c11b3317601c52602090208101810180546001600160a01b03948516949384169381169190828614830261157357826115655763ceea21b66000526004601cfd5b63a11481006000526004601cfd5b846115865763ea553b346000526004601cfd5b8560005281600101549250823314863314176115b4576030600c20546115b457634b6e7f186000526004601cfd5b82156115c257600082600101555b85851818905550601c600c8181208054600019019055600084905220805460010163ffffffff81166115fc576301336cea6000526004601cfd5b90558082847fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600038a45b505050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60008060008661168a876131d7565b61169b611696896131d7565b613222565b6116ac6116a78a6131d7565b613312565b6040516020016116bf949392919061511e565b60408051601f19818403018152908290526004805463040a7bb160e41b84529193506001600160a01b03909116916340a7bb1091611707918c91309187918c918c91016151be565b6040805180830381865afa158015611723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117479190615212565b92509250509550959350505050565b61ffff831660009081526005602052604081208054829190611777906150d4565b80601f01602080910402602001604051908101604052809291908181526020018280546117a3906150d4565b80156117f05780601f106117c5576101008083540402835291602001916117f0565b820191906000526020600020905b8154815290600101906020018083116117d357829003601f168201915b50505050509050838360405161180792919061510e565b60405180910390208180519060200120149150505b9392505050565b61182e838383611515565b813b1561162757611627838383604051806020016040528060008152506133c3565b61185a3382613447565b6118c05760405162461bcd60e51b815260206004820152603160248201527f596f75417265486572653a206275726e2063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606482015260840161113b565b6118c9816134b3565b50565b6118d461311b565b600480546040516342d65a8d60e01b81526001600160a01b03909116916342d65a8d91611907918791879187910161525f565b600060405180830381600087803b15801561192157600080fd5b505af11580156112ef573d6000803e3d6000fd5b601154600160a01b900460ff161561195f5760405162461bcd60e51b815260040161113b9061527d565b6011546001600160a01b031633146119a95760405162461bcd60e51b815260206004820152600d60248201526c4e4f545f434c41494d41424c4560981b604482015260640161113b565b6119b2466134be565b6011805460ff60a01b1916600160a01b1790556119cf33466134e9565b565b6112ef8787876119e0886131d7565b6119ec6116968a6131d7565b6119f86116a78b6131d7565b898989613597565b611a0861311b565b611627838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250613771915050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6060611a8d82613831565b611aa95760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b031663b10c9af583611ac481613855565b6040518363ffffffff1660e01b8152600401611ae19291906152c8565b600060405180830381865afa158015611afe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113329190810190615311565b6000818152673ec412a9852d173d60c11b601c526020902081018101546001600160a01b031680611b5f5763ceea21b66000526004601cfd5b919050565b333014611bc25760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b606482015260840161113b565b611c388686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506139cd92505050565b505050505050565b601154600160a01b900460ff1615611c6a5760405162461bcd60e51b815260040161113b9061527d565b4260105410611caa5760405162461bcd60e51b815260206004820152600c60248201526b4e4f545f4d494e5441424c4560a01b604482015260640161113b565b600f543414611ce35760405162461bcd60e51b8152602060048201526005602482015264505249434560d81b604482015260640161113b565b611cec466134be565b6011805460ff60a01b1916600160a01b1790556118c981466134e9565b611d1161311b565b828114611d605760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20696e76616c696420696e707574206c656e6774680000000000604482015260640161113b565b60005b8381101561139f57828282818110611d7d57611d7d615359565b9050602002810190611d8f919061536f565b30604051602001611da2939291906153b5565b60405160208183030381529060405260056000878785818110611dc757611dc7615359565b9050602002016020810190611ddc9190614662565b61ffff168152602081019190915260400160002090611dfb9082615421565b5080611e06816154f6565b915050611d63565b600081611e2357638f4eb6046000526004601cfd5b673ec412a9852d173d60c11b601c528160005263ffffffff601c600c2054169050919050565b611e5161311b565b6119cf6000613b2e565b60056020526000908152604090208054611e74906150d4565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea0906150d4565b8015611eed5780601f10611ec257610100808354040283529160200191611eed565b820191906000526020600020905b815481529060010190602001808311611ed057829003601f168201915b505050505081565b611efd61311b565b601180546001600160a01b0319166001600160a01b0392909216919091179055565b611f2761311b565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114611f74576040519150601f19603f3d011682016040523d82523d6000602084013e611f79565b606091505b50509050806113f057600080fd5b6000611f9282613831565b15611fa05761133282611b26565b506000919050565b611fb061311b565b828114611fff5760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20696e76616c696420696e707574206c656e6774680000000000604482015260640161113b565b60005b8381101561139f5782828281811061201c5761201c615359565b905060200281019061202e919061536f565b6005600088888681811061204457612044615359565b90506020020160208101906120599190614662565b61ffff16815260208101919091526040016000209161207991908361550f565b5080612084816154f6565b915050612002565b61209461311b565b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6120be613b6c565b80516020808301919091206000818152600e90925260409091206002015460ff1661211f5760405162461bcd60e51b81526020600482015260116024820152701b9bc818dc99591a5d1cc81cdd1bdc9959607a1b604482015260640161113b565b6000806000848060200190518101906121389190615649565b6000888152600e602052604081208054600190910154949850929650909450925061217b9161ffff8216916201000090046001600160a01b031690878787613bc5565b6000868152600e602052604090206001015490915081116121f05760405162461bcd60e51b815260206004820152602960248201527f6e6f7420656e6f7567682067617320746f2070726f6365737320637265646974604482015268103a3930b739b332b960b91b606482015260840161113b565b83518103612267576000858152600e602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba2339061225a9087815260200190565b60405180910390a1612376565b6040518060800160405280600e600088815260200190815260200160002060000160009054906101000a900461ffff1661ffff168152602001600e600088815260200190815260200160002060000160029054906101000a90046001600160a01b03166001600160a01b0316815260200182815260200160011515815250600e600087815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816001015560608201518160020160006101000a81548160ff0219169083151502179055509050505b50505050506118c96001600a55565b61238d61311b565b601154600160a01b900460ff166123d35760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b604482015260640161113b565b4660009081526002602052604081205490036123f2576123f2466134be565b6118c981466134e9565b61240461311b565b600f55565b61241161311b565b601055565b61241e61311b565b600081116124795760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b606482015260840161113b565b61ffff82166000818152600c6020908152604091829020849055815192835282018390527f7315f7654d594ead24a30160ed9ba2d23247f543016b918343591e93d7afdb6d91015b60405180910390a15050565b61ffff81166000908152600560205260408120805460609291906124f0906150d4565b80601f016020809104026020016040519081016040528092919081815260200182805461251c906150d4565b80156125695780601f1061253e57610100808354040283529160200191612569565b820191906000526020600020905b81548152906001019060200180831161254c57829003601f168201915b5050505050905080516000036125c15760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f7264000000604482015260640161113b565b61181c6000601483516125d4919061578f565b839190613c50565b6060600082516001600160401b038111156125f9576125f9614761565b604051908082528060200260200182016040528015612622578160200160208202803683370190505b50905060005b835181101561268f5761265384828151811061264657612646615359565b6020026020010151611f87565b82828151811061266557612665615359565b6001600160a01b039092166020928302919091019091015280612687816154f6565b915050612628565b5092915050565b801515905081601c52670a5a2e7a0000000060085233600052806030600c2055806000528160601b60601c337f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160206000a35050565b6126f461311b565b818130604051602001612709939291906153b5565b60408051601f1981840301815291815261ffff85166000908152600560205220906127349082615421565b50505050565b6112ef8787878761274a89613222565b6119f88a613312565b61275b61311b565b601154600160a81b900460ff16156127855760405162461bcd60e51b815260040161113b9061527d565b466001148061279657504662aa36a7145b806127a2575046617a69145b6127dc5760405162461bcd60e51b815260206004820152600b60248201526a1393d517d350525393915560aa1b604482015260640161113b565b6011805460ff60a81b1916600160a81b1790556127fa610fff6134be565b61280662ffffff6134be565b612814640fffffffff6134be565b61282081610fff6134e9565b61282d8162ffffff6134e9565b6118c981640fffffffff6134e9565b612847858585611515565b833b1561139f5761139f85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133c392505050565b61289861311b565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611489565b6012546040516303c0bff160e41b81526060916001600160a01b031690633c0bff109061291990869086906004016152c8565b600060405180830381865afa158015612936573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261181c9190810190615311565b61296661311b565b601154600160a01b900460ff1615611ce35760405162461bcd60e51b815260040161113b9061527d565b606061133282613855565b60606129a682613831565b6129c25760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b0316638c63e25b836129dd81613855565b600086815260036020526040908190205490516001600160e01b031960e086901b168152611ae1939291906004016157a2565b612a1861311b565b600480546040516332fb62e760e21b81526001600160a01b039091169163cbed8b9c91612a4f9189918991899189918991016157cb565b600060405180830381600087803b158015612a6957600080fd5b505af1158015612a7d573d6000803e3d6000fd5b505050505050505050565b612a9061311b565b60008111612aec5760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b606482015260840161113b565b61ffff82166000818152600d6020908152604091829020849055815192835282018390527fc46df2983228ac2d9754e94a0d565e6671665dc8ad38602bc8e544f0685a29fb91016124c1565b6060612b4382613831565b612b5f5760405162461bcd60e51b815260040161113b906152a5565b6012546001600160a01b0316633c0bff1083611ac481613855565b61ffff86166000908152600960205260408082209051612b9d908890889061510e565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080612c1d5760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b606482015260840161113b565b808383604051612c2e92919061510e565b604051809103902014612c8d5760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b606482015260840161113b565b61ffff87166000908152600960205260408082209051612cb0908990899061510e565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252612d48918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506139cd92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e58787878785604051612d7f9594939291906157f9565b60405180910390a150505050505050565b612d9861311b565b6004546001600160a01b031615612df15760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206c7a456e64706f696e7420616c726561647920736574000000604482015260640161113b565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b612e1b61311b565b61ffff92831660009081526006602090815260408083209490951682529290925291902055565b6060600082516001600160401b03811115612e5f57612e5f614761565b604051908082528060200260200182016040528015612e9257816020015b6060815260200190600190039081612e7d5790505b50905060005b835181101561268f57612ec3848281518110612eb657612eb6615359565b6020026020010151613855565b828281518110612ed557612ed5615359565b60200260200101819052508080612eeb906154f6565b915050612e98565b6060600080600080612f04866125dc565b601054601154600f54929991985060ff600160a01b82041697509195506001600160a01b039091169350915050565b60125460405163b10c9af560e01b81526060916001600160a01b03169063b10c9af59061291990869086906004016152c8565b612f6e61311b565b61ffff8316600090815260056020526040902061273482848361550f565b612f9461311b565b63389a75e1600c52806000526020600c208054421115612fbc57636f5e88186000526004601cfd5b600090556118c981613b2e565b60008060008686612fd988613222565b6116ac89613312565b612fea61311b565b8060601b61300057637448fbae6000526004601cfd5b6118c981613b2e565b60048054604051633d7b2f6f60e21b815261ffff808816938201939093529185166024830152306044830152606482018390526060916001600160a01b039091169063f5ecbdbc90608401600060405180830381865afa158015613071573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130999190810190615834565b95945050505050565b6000806131055a60966366ad5c8a60e01b898989896040516024016130ca9493929190615868565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190613d5d565b9150915081611c3857611c388686868685613de7565b638b78c6d8195433146119cf576382b429006000526004601cfd5b60001960601c828116925083811693508160005283673ec412a9852d173d60c11b17601c526020600020820182018054821691508161317d5763ceea21b66000526004601cfd5b8185148515176131a357816000526030600c20546131a357634b6e7f186000526004601cfd5b6001018390558183827f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600038a450505050565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061321157613211615359565b602090810291909101015292915050565b6060600082516001600160401b0381111561323f5761323f614761565b60405190808252806020026020018201604052801561327857816020015b6132656144b3565b81526020019060019003908161325d5790505b50905060005b835181101561268f576002600085838151811061329d5761329d615359565b60209081029190910181015182528101919091526040908101600020815160808101928390529160049082845b8154815260200190600101908083116132ca5750505050508282815181106132f4576132f4615359565b6020026020010181905250808061330a906154f6565b91505061327e565b6060600082516001600160401b0381111561332f5761332f614761565b604051908082528060200260200182016040528015613358578160200160208202803683370190505b50905060005b835181101561268f576003600085838151811061337d5761337d615359565b60200260200101518152602001908152602001600020548282815181106133a6576133a6615359565b6020908102919091010152806133bb816154f6565b91505061335e565b60405163150b7a028082523360208301528560601b60601c604083015283606083015260808083015282518060a0840152801561340a578060c08401826020870160045afa505b60208360a48301601c860160008a5af161342d573d1561342d573d6000843e3d83fd5b508060e01b825114611c385763d1a57ed66000526004601cfd5b60008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c5260209091208201820180549193600192168061348c5763ceea21b66000526004601cfd5b8085146134ab57806000526030600c20546134ab578160010154851492505b505092915050565b6118c9600082613e84565b4660009081526001602081815260408084205494845260028252808420949094556003905291902055565b6001600160a01b0390911690816135085763ea553b346000526004601cfd5b80600052673ec412a9852d173d60c11b601c5260206000208101810180548060601b1561353d5763c991cbb16000526004601cfd5b831790556000829052601c600c20805460010163ffffffff8116613569576301336cea6000526004601cfd5b9055808260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8138a45050565b60008651116135de5760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b604482015260640161113b565b855160011480613602575061ffff88166000908152600c6020526040902054865111155b6136595760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b606482015260840161113b565b60005b865181101561369c5761368a8a8a8a8a858151811061367d5761367d615359565b6020026020010151613f52565b80613694816154f6565b91505061365c565b506000878787876040516020016136b6949392919061511e565b60405160208183030381529060405290506136fb896001848a51600d60008f61ffff1661ffff168152602001908152602001600020546136f691906158a6565b614042565b613709898286868634614129565b8760405161371791906158bd565b60405180910390208a6001600160a01b03168a61ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a8a60405161375d9190614eb5565b60405180910390a450505050505050505050565b61010082518261378191906158d9565b11156137a057604051630fb9d71f60e11b815260040160405180910390fd5b60005b8251811015611627578281815181106137be576137be615359565b602002602001015160008083856137d591906158d9565b81526020810191909152604001600020556137f081836158d9565b6001600085848151811061380657613806615359565b60200260200101518152602001908152602001600020819055508061382a906154f6565b90506137a3565b6000818152673ec412a9852d173d60c11b601c52602090208101015460601b151590565b600081815260036020526040812054606091608082116138755781613878565b60805b90506000816001600160401b0381111561389457613894614761565b6040519080825280602002602001820160405280156138bd578160200160208202803683370190505b50600086815260026020526040808220815160808101928390529394509192919060049082845b8154815260200190600101908083116138e4575050505050905060005b82518110156139c257600060808261391a60018961578f565b613924919061578f565b61392e9190615902565b9050600061393d602083615916565b9050600061394c602084615902565b6139579060086158a6565b905060008186846004811061396e5761396e615359565b6020020151901c60ff1690506000808281526020019081526020016000205487868151811061399f5761399f615359565b6020026020010181815250505050505080806139ba906154f6565b915050613901565b509095945050505050565b600080600080848060200190518101906139e79190615649565b6014840151939750919550935091506000613a068a8383888888613bc5565b90508451811015613ada5786516020808901919091206040805160808101825261ffff808f1682526001600160a01b038088168387019081528385018881526001606086018181526000898152600e909a529887902095518654935190941662010000026001600160b01b03199093169390941692909217178355519082015592516002909301805493151560ff199094169390931790925590517f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad790613ad09083908b9061592a565b60405180910390a1505b816001600160a01b031689604051613af291906158bd565b60405180910390208b61ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d9902658860405161375d9190614eb5565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b6002600a5403613bbe5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161113b565b6002600a55565b6000845b8451811015613c4557600b545a10613c4557613c338888878481518110613bf257613bf2615359565b6020026020010151878581518110613c0c57613c0c615359565b6020026020010151878681518110613c2657613c26615359565b60200260200101516142b1565b80613c3d816154f6565b915050613bc9565b979650505050505050565b606081613c5e81601f6158d9565b1015613c9d5760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161113b565b613ca782846158d9565b84511015613ceb5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161113b565b606082158015613d0a5760405191506000825260208201604052613d54565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613d43578051835260209283019201613d2b565b5050858452601f01601f1916604052505b50949350505050565b6000606060008060008661ffff166001600160401b03811115613d8257613d82614761565b6040519080825280601f01601f191660200182016040528015613dac576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115613dce578692505b828152826000602083013e909890975095505050505050565b8180519060200120600960008761ffff1661ffff16815260200190815260200160002085604051613e1891906158bd565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c90613e759087908790879087908790615943565b60405180910390a15050505050565b6000613e8f82611b26565b90505060008181526001600160a01b03928316673ec412a9852d173d60c11b8117601c526020909120820182018054919382169182613ed65763ceea21b66000526004601cfd5b82600052816001015480861484871417861517613f05576030600c2054613f0557634b6e7f186000526004601cfd5b8015613f1357600083600101555b5082189055601c600c208054600019019055816000827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8238a4505050565b613f5c3382613447565b613fc25760405162461bcd60e51b815260206004820152603160248201527f596f75417265486572653a2073656e642063616c6c6572206973206e6f74206f6044820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606482015260840161113b565b836001600160a01b0316613fd582611b26565b6001600160a01b0316146140395760405162461bcd60e51b815260206004820152602560248201527f596f75417265486572653a2073656e642066726f6d20696e636f72726563742060448201526437bbb732b960d91b606482015260840161113b565b612734816134b3565b600061404d836142d9565b61ffff80871660009081526006602090815260408083209389168352929052908120549192508190036140805750620249f05b600081116140d05760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f7420736574000000000000604482015260640161113b565b6140da83826158d9565b821015611c385760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f770000000000604482015260640161113b565b61ffff861660009081526005602052604081208054614147906150d4565b80601f0160208091040260200160405190810160405280929190818152602001828054614173906150d4565b80156141c05780601f10614195576101008083540402835291602001916141c0565b820191906000526020600020905b8154815290600101906020018083116141a357829003601f168201915b5050505050905080516000036142315760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b606482015260840161113b565b61423c878751614335565b6004805460405162c5803160e81b81526001600160a01b039091169163c5803100918591614276918c9187918d918d918d918d9101615995565b6000604051808303818588803b15801561428f57600080fd5b505af11580156142a3573d6000803e3d6000fd5b505050505050505050505050565b6142ba83613831565b156142c457600080fd5b6142cf8383836143a6565b61139f84846134e9565b600060228251101561432d5760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d7300000000604482015260640161113b565b506022015190565b61ffff82166000908152600760205260408120549081900361435657506127105b808211156116275760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c61726765604482015260640161113b565b60006143b3608083615902565b905060006143c2602083615916565b905060006143d1602084615902565b6143dc9060086158a6565b905060ff811b196000818785600481106143f8576143f8615359565b6020020151169050826001600046815260200190815260200160002054901b811787856004811061442b5761442b615359565b602002015260005b600481101561448b5787816004811061444e5761444e615359565b6020020151600260008b8152602001908152602001600020826004811061447757614477615359565b015580614483816154f6565b915050614433565b506144978660016158d9565b6000988952600360205260409098209790975550505050505050565b60405180608001604052806004906020820280368337509192915050565b803561ffff81168114611b5f57600080fd5b60008083601f8401126144f557600080fd5b5081356001600160401b0381111561450c57600080fd5b60208301915083602082850101111561452457600080fd5b9250929050565b80356001600160401b0381168114611b5f57600080fd5b6000806000806000806080878903121561455b57600080fd5b614564876144d1565b955060208701356001600160401b038082111561458057600080fd5b61458c8a838b016144e3565b90975095508591506145a060408a0161452b565b945060608901359150808211156145b657600080fd5b506145c389828a016144e3565b979a9699509497509295939492505050565b6000602082840312156145e757600080fd5b81356001600160e01b03198116811461181c57600080fd5b60005b8381101561461a578181015183820152602001614602565b50506000910152565b6000815180845261463b8160208601602086016145ff565b601f01601f19169290920160200192915050565b60208152600061181c6020830184614623565b60006020828403121561467457600080fd5b61181c826144d1565b60006020828403121561468f57600080fd5b5035919050565b6001600160a01b03811681146118c957600080fd5b8035611b5f81614696565b600080604083850312156146c957600080fd5b82356146d481614696565b946020939093013593505050565b600080604083850312156146f557600080fd5b6146d4836144d1565b6000806040838503121561471157600080fd5b50508035926020909101359150565b60008060006060848603121561473557600080fd5b833561474081614696565b9250602084013561475081614696565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171561479957614799614761565b60405290565b604051601f8201601f191681016001600160401b03811182821017156147c7576147c7614761565b604052919050565b60006001600160401b038211156147e8576147e8614761565b50601f01601f191660200190565b600082601f83011261480757600080fd5b813561481a614815826147cf565b61479f565b81815284602083860101111561482f57600080fd5b816020850160208301376000918101602001919091529392505050565b80358015158114611b5f57600080fd5b600080600080600060a0868803121561487457600080fd5b61487d866144d1565b945060208601356001600160401b038082111561489957600080fd5b6148a589838a016147f6565b9550604088013594506148ba6060890161484c565b935060808801359150808211156148d057600080fd5b506148dd888289016147f6565b9150509295509295909350565b6000806000604084860312156148ff57600080fd5b614908846144d1565b925060208401356001600160401b0381111561492357600080fd5b61492f868287016144e3565b9497909650939450505050565b600080600080600080600060e0888a03121561495757600080fd5b873561496281614696565b9650614970602089016144d1565b955060408801356001600160401b038082111561498c57600080fd5b6149988b838c016147f6565b965060608a0135955060808a013591506149b182614696565b90935060a0890135906149c382614696565b90925060c089013590808211156149d957600080fd5b506149e68a828b016147f6565b91505092959891949750929550565b60008083601f840112614a0757600080fd5b5081356001600160401b03811115614a1e57600080fd5b6020830191508360208260051b850101111561452457600080fd5b600080600060408486031215614a4e57600080fd5b83356001600160401b03811115614a6457600080fd5b614a70868287016149f5565b909790965060209590950135949350505050565b600080600060608486031215614a9957600080fd5b614aa2846144d1565b925060208401356001600160401b03811115614abd57600080fd5b614ac9868287016147f6565b925050614ad86040850161452b565b90509250925092565b600060208284031215614af357600080fd5b813561181c81614696565b60008060008060408587031215614b1457600080fd5b84356001600160401b0380821115614b2b57600080fd5b614b37888389016149f5565b90965094506020870135915080821115614b5057600080fd5b50614b5d878288016149f5565b95989497509550505050565b60008060408385031215614b7c57600080fd5b614b85836144d1565b9150614b93602084016144d1565b90509250929050565b600060208284031215614bae57600080fd5b81356001600160401b03811115614bc457600080fd5b614bd0848285016147f6565b949350505050565b60006001600160401b03821115614bf157614bf1614761565b5060051b60200190565b600082601f830112614c0c57600080fd5b81356020614c1c61481583614bd8565b82815260059290921b84018101918181019086841115614c3b57600080fd5b8286015b84811015614c565780358352918301918301614c3f565b509695505050505050565b600060208284031215614c7357600080fd5b81356001600160401b03811115614c8957600080fd5b614bd084828501614bfb565b600081518084526020808501945080840160005b83811015614cce5781516001600160a01b031687529582019590820190600101614ca9565b509495945050505050565b60208152600061181c6020830184614c95565b60008060408385031215614cff57600080fd5b8235614d0a81614696565b9150614b936020840161484c565b600080600080600080600060e0888a031215614d3357600080fd5b8735614d3e81614696565b9650614d4c602089016144d1565b955060408801356001600160401b0380821115614d6857600080fd5b614d748b838c016147f6565b965060608a0135915080821115614d8a57600080fd5b614d968b838c01614bfb565b955060808a01359150614da882614696565b819450614db760a08b016146ab565b935060c08a01359150808211156149d957600080fd5b600080600080600060808688031215614de557600080fd5b8535614df081614696565b94506020860135614e0081614696565b93506040860135925060608601356001600160401b03811115614e2257600080fd5b614e2e888289016144e3565b969995985093965092949392505050565b60008060408385031215614e5257600080fd5b8235915060208301356001600160401b03811115614e6f57600080fd5b614e7b85828601614bfb565b9150509250929050565b600081518084526020808501945080840160005b83811015614cce57815187529582019590820190600101614e99565b60208152600061181c6020830184614e85565b600080600080600060808688031215614ee057600080fd5b614ee9866144d1565b9450614e00602087016144d1565b600080600060608486031215614f0c57600080fd5b614f15846144d1565b9250614f23602085016144d1565b9150604084013590509250925092565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614f8857603f19888603018452614f76858351614e85565b94509285019290850190600101614f5a565b5092979650505050505050565b60a081526000614fa860a0830188614c95565b602083019690965250921515604084015260608301919091526001600160a01b0316608090910152919050565b60008060408385031215614fe857600080fd5b8235614ff381614696565b9150602083013561500381614696565b809150509250929050565b600080600080600060a0868803121561502657600080fd5b61502f866144d1565b945060208601356001600160401b038082111561504b57600080fd5b61505789838a016147f6565b9550604088013591508082111561506d57600080fd5b61507989838a01614bfb565b94506148ba6060890161484c565b6000806000806080858703121561509d57600080fd5b6150a6856144d1565b93506150b4602086016144d1565b925060408501356150c481614696565b9396929550929360600135925050565b600181811c908216806150e857607f821691505b60208210810361510857634e487b7160e01b600052602260045260246000fd5b50919050565b8183823760009101908152919050565b6000608080835261513181840188614623565b6020848203818601526151448289614e85565b858103604087015287518082528289019350908201906000805b8281101561519b57855184835b60048110156151885782518252918701919087019060010161516b565b505050948401949286019260010161515e565b50505085810360608701526151b08188614e85565b9a9950505050505050505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906151ec90830186614623565b841515606084015282810360808401526152068185614623565b98975050505050505050565b6000806040838503121561522557600080fd5b505080516020909101519092909150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff84168152604060208201526000613099604083018486615236565b6020808252600e908201526d1053149150511657d3525395115160921b604082015260600190565b6020808252600990820152681393d517d193d5539160ba1b604082015260600190565b828152604060208201526000614bd06040830184614e85565b60006152ef614815846147cf565b905082815283838301111561530357600080fd5b61181c8360208301846145ff565b60006020828403121561532357600080fd5b81516001600160401b0381111561533957600080fd5b8201601f8101841361534a57600080fd5b614bd0848251602084016152e1565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261538657600080fd5b8301803591506001600160401b038211156153a057600080fd5b60200191503681900382131561452457600080fd5b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f82111561162757600081815260208120601f850160051c810160208610156154025750805b601f850160051c820191505b81811015611c385782815560010161540e565b81516001600160401b0381111561543a5761543a614761565b61544e8161544884546150d4565b846153db565b602080601f831160018114615483576000841561546b5750858301515b600019600386901b1c1916600185901b178555611c38565b600085815260208120601f198616915b828110156154b257888601518255948401946001909101908401615493565b50858210156154d05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600060018201615508576155086154e0565b5060010190565b6001600160401b0383111561552657615526614761565b61553a8361553483546150d4565b836153db565b6000601f84116001811461556e57600085156155565750838201355b600019600387901b1c1916600186901b17835561139f565b600083815260209020601f19861690835b8281101561559f578685013582556020948501946001909201910161557f565b50868210156155bc5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b600082601f8301126155df57600080fd5b61181c838351602085016152e1565b600082601f8301126155ff57600080fd5b8151602061560f61481583614bd8565b82815260059290921b8401810191818101908684111561562e57600080fd5b8286015b84811015614c565780518352918301918301615632565b600080600080608080868803121561566057600080fd5b85516001600160401b038082111561567757600080fd5b61568389838a016155ce565b965060209150818801518181111561569a57600080fd5b6156a68a828b016155ee565b9650506040880151818111156156bb57600080fd5b8801601f81018a136156cc57600080fd5b80516156da61481582614bd8565b81815260079190911b8201840190848101908c8311156156f957600080fd5b928501925b8284101561575b578c601f8501126157165760008081fd5b61571e614777565b808886018f8111156157305760008081fd5b865b818110156157495780518452928901928901615732565b505083525092860192908501906156fe565b60608c015190985095505050508083111561577557600080fd5b5050615783878288016155ee565b91505092959194509250565b81810381811115611332576113326154e0565b8381526060602082015260006157bb6060830185614e85565b9050826040830152949350505050565b600061ffff808816835280871660208401525084604083015260806060830152613c45608083018486615236565b61ffff86168152608060208201526000615817608083018688615236565b6001600160401b0394909416604083015250606001529392505050565b60006020828403121561584657600080fd5b81516001600160401b0381111561585c57600080fd5b614bd0848285016155ce565b61ffff851681526080602082015260006158856080830186614623565b6001600160401b03851660408401528281036060840152613c458185614623565b8082028115828204841417611332576113326154e0565b600082516158cf8184602087016145ff565b9190910192915050565b80820180821115611332576113326154e0565b634e487b7160e01b600052601260045260246000fd5b600082615911576159116158ec565b500690565b600082615925576159256158ec565b500490565b828152604060208201526000614bd06040830184614623565b61ffff8616815260a06020820152600061596060a0830187614623565b6001600160401b038616604084015282810360608401526159818186614623565b905082810360808401526152068185614623565b61ffff8716815260c0602082015260006159b260c0830188614623565b82810360408401526159c48188614623565b6001600160a01b0387811660608601528616608085015283810360a085015290506159ef8185614623565b999850505050505050505056fea2646970667358221220ac8b222083a89263f1e1a3d7e7f7909d91b30a156ddb36f7a1b9d1e1cd9e2ab464736f6c63430008130033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.