ETH Price: $2,291.52 (-4.92%)

Token

 

Overview

Max Total Supply

0

Holders

0

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
ProxyOFTWithFee

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-01-08
*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

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

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;
}

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;
}

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);
}

/*
 * @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.
 */
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;
    }
}

/*
 * 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 = 10000;

    ILayerZeroEndpoint public immutable 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);

    constructor(address _endpoint) {
        lzEndpoint = ILayerZeroEndpoint(_endpoint);
    }

    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(_msgSender() == 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];
        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 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);
    }
}

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)
        }
    }
}

/*
 * 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(address _endpoint) LzApp(_endpoint) {}

    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(_msgSender() == 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);
    }
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
/**
 * @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);
}

/**
 * @dev Interface of the IOFT core standard
 */
interface ICommonOFT is IERC165 {
    struct LzCallParams {
        address payable refundAddress;
        address zroPaymentAddress;
        bytes adapterParams;
    }

    /**
     * @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
     * _amount - amount of the tokens to transfer
     * _useZro - indicates to use zro to pay L0 fees
     * _adapterParam - flexible bytes array to indicate messaging adapter services in L0
     */
    function estimateSendFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bool _useZro,
        bytes calldata _adapterParams
    ) external view returns (uint nativeFee, uint zroFee);

    function estimateSendAndCallFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bytes calldata _payload,
        uint64 _dstGasForCall,
        bool _useZro,
        bytes calldata _adapterParams
    ) external view returns (uint nativeFee, uint zroFee);

    /**
     * @dev returns the circulating amount of tokens on current chain
     */
    function circulatingSupply() external view returns (uint);

    /**
     * @dev returns the address of the ERC20 token
     */
    function token() external view returns (address);
}

interface IOFTReceiverV2 {
    /**
     * @dev Called by the OFT contract when tokens are received from source chain.
     * @param _srcChainId The chain id of the source chain.
     * @param _srcAddress The address of the OFT token contract on the source chain.
     * @param _nonce The nonce of the transaction on the source chain.
     * @param _from The address of the account who calls the sendAndCall() on the source chain.
     * @param _amount The amount of tokens to transfer.
     * @param _payload Additional data with no specified format.
     */
    function onOFTReceived(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes32 _from,
        uint _amount,
        bytes calldata _payload
    ) external;
}

abstract contract OFTCoreV2 is NonblockingLzApp {
    using BytesLib for bytes;
    using ExcessivelySafeCall for address;

    uint public constant NO_EXTRA_GAS = 0;

    // packet type
    uint8 public constant PT_SEND = 0;
    uint8 public constant PT_SEND_AND_CALL = 1;

    uint8 public immutable sharedDecimals;

    mapping(uint16 => mapping(bytes => mapping(uint64 => bool))) public creditedPackets;

    /**
     * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`)
     * `_nonce` is the outbound nonce
     */
    event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes32 indexed _toAddress, uint _amount);

    /**
     * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain.
     * `_nonce` is the inbound nonce.
     */
    event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint _amount);

    event CallOFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _hash);

    event NonContractAddress(address _address);

    // _sharedDecimals should be the minimum decimals on all chains
    constructor(uint8 _sharedDecimals, address _lzEndpoint) NonblockingLzApp(_lzEndpoint) {
        sharedDecimals = _sharedDecimals;
    }

    /************************************************************************
     * public functions
     ************************************************************************/
    function callOnOFTReceived(
        uint16 _srcChainId,
        bytes calldata _srcAddress,
        uint64 _nonce,
        bytes32 _from,
        address _to,
        uint _amount,
        bytes calldata _payload,
        uint _gasForCall
    ) public virtual {
        require(_msgSender() == address(this), "OFTCore: caller must be OFTCore");

        // send
        _amount = _transferFrom(address(this), _to, _amount);
        emit ReceiveFromChain(_srcChainId, _to, _amount);

        // call
        IOFTReceiverV2(_to).onOFTReceived{gas: _gasForCall}(_srcChainId, _srcAddress, _nonce, _from, _amount, _payload);
    }

    /************************************************************************
     * internal functions
     ************************************************************************/
    function _estimateSendFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bool _useZro,
        bytes memory _adapterParams
    ) internal view virtual returns (uint nativeFee, uint zroFee) {
        // mock the payload for sendFrom()
        bytes memory payload = _encodeSendPayload(_toAddress, _ld2sd(_amount));
        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
    }

    function _estimateSendAndCallFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bytes memory _payload,
        uint64 _dstGasForCall,
        bool _useZro,
        bytes memory _adapterParams
    ) internal view virtual returns (uint nativeFee, uint zroFee) {
        // mock the payload for sendAndCall()
        bytes memory payload = _encodeSendAndCallPayload(msg.sender, _toAddress, _ld2sd(_amount), _payload, _dstGasForCall);
        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
    }

    function _nonblockingLzReceive(
        uint16 _srcChainId,
        bytes memory _srcAddress,
        uint64 _nonce,
        bytes memory _payload
    ) internal virtual override {
        uint8 packetType = _payload.toUint8(0);

        if (packetType == PT_SEND) {
            _sendAck(_srcChainId, _srcAddress, _nonce, _payload);
        } else if (packetType == PT_SEND_AND_CALL) {
            _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload);
        } else {
            revert("OFTCore: unknown packet type");
        }
    }

    function _send(
        address _from,
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams
    ) internal virtual returns (uint amount) {
        _checkGasLimit(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS);

        (amount, ) = _removeDust(_amount);
        amount = _debitFrom(_from, _dstChainId, _toAddress, amount); // amount returned should not have dust
        require(amount > 0, "OFTCore: amount too small");

        bytes memory lzPayload = _encodeSendPayload(_toAddress, _ld2sd(amount));
        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);

        emit SendToChain(_dstChainId, _from, _toAddress, amount);
    }

    function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual {
        (address to, uint64 amountSD) = _decodeSendPayload(_payload);
        if (to == address(0)) {
            to = address(0xdead);
        }

        uint amount = _sd2ld(amountSD);
        amount = _creditTo(_srcChainId, to, amount);

        emit ReceiveFromChain(_srcChainId, to, amount);
    }

    function _sendAndCall(
        address _from,
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bytes memory _payload,
        uint64 _dstGasForCall,
        address payable _refundAddress,
        address _zroPaymentAddress,
        bytes memory _adapterParams
    ) internal virtual returns (uint amount) {
        _checkGasLimit(_dstChainId, PT_SEND_AND_CALL, _adapterParams, _dstGasForCall);

        (amount, ) = _removeDust(_amount);
        amount = _debitFrom(_from, _dstChainId, _toAddress, amount);
        require(amount > 0, "OFTCore: amount too small");

        // encode the msg.sender into the payload instead of _from
        bytes memory lzPayload = _encodeSendAndCallPayload(msg.sender, _toAddress, _ld2sd(amount), _payload, _dstGasForCall);
        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);

        emit SendToChain(_dstChainId, _from, _toAddress, amount);
    }

    function _sendAndCallAck(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual {
        (bytes32 from, address to, uint64 amountSD, bytes memory payloadForCall, uint64 gasForCall) = _decodeSendAndCallPayload(_payload);

        bool credited = creditedPackets[_srcChainId][_srcAddress][_nonce];
        uint amount = _sd2ld(amountSD);

        // credit to this contract first, and then transfer to receiver only if callOnOFTReceived() succeeds
        if (!credited) {
            amount = _creditTo(_srcChainId, address(this), amount);
            creditedPackets[_srcChainId][_srcAddress][_nonce] = true;
        }

        if (!_isContract(to)) {
            emit NonContractAddress(to);
            return;
        }

        // workaround for stack too deep
        uint16 srcChainId = _srcChainId;
        bytes memory srcAddress = _srcAddress;
        uint64 nonce = _nonce;
        bytes memory payload = _payload;
        bytes32 from_ = from;
        address to_ = to;
        uint amount_ = amount;
        bytes memory payloadForCall_ = payloadForCall;

        // no gas limit for the call if retry
        uint gas = credited ? gasleft() : gasForCall;
        (bool success, bytes memory reason) = address(this).excessivelySafeCall(
            gasleft(),
            150,
            abi.encodeWithSelector(this.callOnOFTReceived.selector, srcChainId, srcAddress, nonce, from_, to_, amount_, payloadForCall_, gas)
        );

        if (success) {
            bytes32 hash = keccak256(payload);
            emit CallOFTReceivedSuccess(srcChainId, srcAddress, nonce, hash);
        } else {
            // store the failed message into the nonblockingLzApp
            _storeFailedMessage(srcChainId, srcAddress, nonce, payload, reason);
        }
    }

    function _isContract(address _account) internal view returns (bool) {
        return _account.code.length > 0;
    }

    function _ld2sd(uint _amount) internal view virtual returns (uint64) {
        uint amountSD = _amount / _ld2sdRate();
        require(amountSD <= type(uint64).max, "OFTCore: amountSD overflow");
        return uint64(amountSD);
    }

    function _sd2ld(uint64 _amountSD) internal view virtual returns (uint) {
        return _amountSD * _ld2sdRate();
    }

    function _removeDust(uint _amount) internal view virtual returns (uint amountAfter, uint dust) {
        dust = _amount % _ld2sdRate();
        amountAfter = _amount - dust;
    }

    function _encodeSendPayload(bytes32 _toAddress, uint64 _amountSD) internal view virtual returns (bytes memory) {
        return abi.encodePacked(PT_SEND, _toAddress, _amountSD);
    }

    function _decodeSendPayload(bytes memory _payload) internal view virtual returns (address to, uint64 amountSD) {
        require(_payload.toUint8(0) == PT_SEND && _payload.length == 41, "OFTCore: invalid payload");

        to = _payload.toAddress(13); // drop the first 12 bytes of bytes32
        amountSD = _payload.toUint64(33);
    }

    function _encodeSendAndCallPayload(
        address _from,
        bytes32 _toAddress,
        uint64 _amountSD,
        bytes memory _payload,
        uint64 _dstGasForCall
    ) internal view virtual returns (bytes memory) {
        return abi.encodePacked(PT_SEND_AND_CALL, _toAddress, _amountSD, _addressToBytes32(_from), _dstGasForCall, _payload);
    }

    function _decodeSendAndCallPayload(
        bytes memory _payload
    ) internal view virtual returns (bytes32 from, address to, uint64 amountSD, bytes memory payload, uint64 dstGasForCall) {
        require(_payload.toUint8(0) == PT_SEND_AND_CALL, "OFTCore: invalid payload");

        to = _payload.toAddress(13); // drop the first 12 bytes of bytes32
        amountSD = _payload.toUint64(33);
        from = _payload.toBytes32(41);
        dstGasForCall = _payload.toUint64(73);
        payload = _payload.slice(81, _payload.length - 81);
    }

    function _addressToBytes32(address _address) internal pure virtual returns (bytes32) {
        return bytes32(uint(uint160(_address)));
    }

    function _debitFrom(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount) internal virtual returns (uint);

    function _creditTo(uint16 _srcChainId, address _toAddress, uint _amount) internal virtual returns (uint);

    function _transferFrom(address _from, address _to, uint _amount) internal virtual returns (uint);

    function _ld2sdRate() internal view virtual returns (uint);
}

/**
 * @dev Interface of the IOFT core standard
 */
interface IOFTWithFee is ICommonOFT {
    /**
     * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`
     * `_from` the owner of token
     * `_dstChainId` the destination chain identifier
     * `_toAddress` can be any size depending on the `dstChainId`.
     * `_amount` the quantity of tokens in wei
     * `_minAmount` the minimum amount of tokens to receive on dstChain
     * `_refundAddress` the address LayerZero refunds if too much message fee is sent
     * `_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,
        bytes32 _toAddress,
        uint _amount,
        uint _minAmount,
        LzCallParams calldata _callParams
    ) external payable;

    function sendAndCall(
        address _from,
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        uint _minAmount,
        bytes calldata _payload,
        uint64 _dstGasForCall,
        LzCallParams calldata _callParams
    ) external payable;
}

abstract contract Fee is Ownable {
    uint public constant BP_DENOMINATOR = 10000;

    mapping(uint16 => FeeConfig) public chainIdToFeeBps;
    uint16 public defaultFeeBp;
    address public feeOwner; // defaults to owner

    struct FeeConfig {
        uint16 feeBP;
        bool enabled;
    }

    event SetFeeBp(uint16 dstchainId, bool enabled, uint16 feeBp);
    event SetDefaultFeeBp(uint16 feeBp);
    event SetFeeOwner(address feeOwner);

    constructor() {
        feeOwner = owner();
    }

    function setDefaultFeeBp(uint16 _feeBp) public virtual onlyOwner {
        require(_feeBp <= BP_DENOMINATOR, "Fee: fee bp must be <= BP_DENOMINATOR");
        defaultFeeBp = _feeBp;
        emit SetDefaultFeeBp(defaultFeeBp);
    }

    function setFeeBp(uint16 _dstChainId, bool _enabled, uint16 _feeBp) public virtual onlyOwner {
        require(_feeBp <= BP_DENOMINATOR, "Fee: fee bp must be <= BP_DENOMINATOR");
        chainIdToFeeBps[_dstChainId] = FeeConfig(_feeBp, _enabled);
        emit SetFeeBp(_dstChainId, _enabled, _feeBp);
    }

    function setFeeOwner(address _feeOwner) public virtual onlyOwner {
        require(_feeOwner != address(0x0), "Fee: feeOwner cannot be 0x");
        feeOwner = _feeOwner;
        emit SetFeeOwner(_feeOwner);
    }

    function quoteOFTFee(uint16 _dstChainId, uint _amount) public view virtual returns (uint fee) {
        FeeConfig memory config = chainIdToFeeBps[_dstChainId];
        if (config.enabled) {
            fee = (_amount * config.feeBP) / BP_DENOMINATOR;
        } else if (defaultFeeBp > 0) {
            fee = (_amount * defaultFeeBp) / BP_DENOMINATOR;
        } else {
            fee = 0;
        }
    }

    function _payOFTFee(address _from, uint16 _dstChainId, uint _amount) internal virtual returns (uint amount, uint fee) {
        fee = quoteOFTFee(_dstChainId, _amount);
        amount = _amount - fee;
        if (fee > 0) {
            _transferFrom(_from, feeOwner, fee);
        }
    }

    function _transferFrom(address _from, address _to, uint _amount) internal virtual returns (uint);
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.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;
    }
}

abstract contract BaseOFTWithFee is OFTCoreV2, Fee, ERC165, IOFTWithFee {
    constructor(uint8 _sharedDecimals, address _lzEndpoint) OFTCoreV2(_sharedDecimals, _lzEndpoint) {}

    /************************************************************************
     * public functions
     ************************************************************************/
    function sendFrom(
        address _from,
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        uint _minAmount,
        LzCallParams calldata _callParams
    ) public payable virtual override {
        (_amount, ) = _payOFTFee(_from, _dstChainId, _amount);
        _amount = _send(
            _from,
            _dstChainId,
            _toAddress,
            _amount,
            _callParams.refundAddress,
            _callParams.zroPaymentAddress,
            _callParams.adapterParams
        );
        require(_amount >= _minAmount, "BaseOFTWithFee: amount is less than minAmount");
    }

    function sendAndCall(
        address _from,
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        uint _minAmount,
        bytes calldata _payload,
        uint64 _dstGasForCall,
        LzCallParams calldata _callParams
    ) public payable virtual override {
        (_amount, ) = _payOFTFee(_from, _dstChainId, _amount);
        _amount = _sendAndCall(
            _from,
            _dstChainId,
            _toAddress,
            _amount,
            _payload,
            _dstGasForCall,
            _callParams.refundAddress,
            _callParams.zroPaymentAddress,
            _callParams.adapterParams
        );
        require(_amount >= _minAmount, "BaseOFTWithFee: amount is less than minAmount");
    }

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

    function estimateSendFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bool _useZro,
        bytes calldata _adapterParams
    ) public view virtual override returns (uint nativeFee, uint zroFee) {
        return _estimateSendFee(_dstChainId, _toAddress, _amount, _useZro, _adapterParams);
    }

    function estimateSendAndCallFee(
        uint16 _dstChainId,
        bytes32 _toAddress,
        uint _amount,
        bytes calldata _payload,
        uint64 _dstGasForCall,
        bool _useZro,
        bytes calldata _adapterParams
    ) public view virtual override returns (uint nativeFee, uint zroFee) {
        return _estimateSendAndCallFee(_dstChainId, _toAddress, _amount, _payload, _dstGasForCall, _useZro, _adapterParams);
    }

    function circulatingSupply() public view virtual override returns (uint);

    function token() public view virtual override returns (address);

    function _transferFrom(address _from, address _to, uint _amount) internal virtual override(Fee, OFTCoreV2) returns (uint);
}

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
     * 0 before setting it to a non-zero value.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

contract ProxyOFTWithFee is BaseOFTWithFee {
    using SafeERC20 for IERC20;

    IERC20 internal immutable innerToken;
    uint internal immutable ld2sdRate;

    // total amount is transferred from this chain to other chains, ensuring the total is less than uint64.max in sd
    uint public outboundAmount;

    constructor(address _token, uint8 _sharedDecimals, address _lzEndpoint) BaseOFTWithFee(_sharedDecimals, _lzEndpoint) {
        innerToken = IERC20(_token);

        (bool success, bytes memory data) = _token.staticcall(abi.encodeWithSignature("decimals()"));
        require(success, "ProxyOFTWithFee: failed to get token decimals");
        uint8 decimals = abi.decode(data, (uint8));

        require(_sharedDecimals <= decimals, "ProxyOFTWithFee: sharedDecimals must be <= decimals");
        ld2sdRate = 10 ** (decimals - _sharedDecimals);
    }

    /************************************************************************
     * public functions
     ************************************************************************/
    function circulatingSupply() public view virtual override returns (uint) {
        return innerToken.totalSupply() - outboundAmount;
    }

    function token() public view virtual override returns (address) {
        return address(innerToken);
    }

    /************************************************************************
     * internal functions
     ************************************************************************/
    function _debitFrom(address _from, uint16, bytes32, uint _amount) internal virtual override returns (uint) {
        require(_from == _msgSender(), "ProxyOFTWithFee: owner is not send caller");

        _amount = _transferFrom(_from, address(this), _amount);

        // _amount still may have dust if the token has transfer fee, then give the dust back to the sender
        (uint amount, uint dust) = _removeDust(_amount);
        if (dust > 0) innerToken.safeTransfer(_from, dust);

        // check total outbound amount
        outboundAmount += amount;
        uint cap = _sd2ld(type(uint64).max);
        require(cap >= outboundAmount, "ProxyOFTWithFee: outboundAmount overflow");

        return amount;
    }

    function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {
        outboundAmount -= _amount;

        // tokens are already in this contract, so no need to transfer
        if (_toAddress == address(this)) {
            return _amount;
        }

        return _transferFrom(address(this), _toAddress, _amount);
    }

    function _transferFrom(address _from, address _to, uint _amount) internal virtual override returns (uint) {
        uint before = innerToken.balanceOf(_to);
        if (_from == address(this)) {
            innerToken.safeTransfer(_to, _amount);
        } else {
            innerToken.safeTransferFrom(_from, _to, _amount);
        }
        return innerToken.balanceOf(_to) - before;
    }

    function _ld2sdRate() internal view virtual override returns (uint) {
        return ld2sdRate;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint8","name":"_sharedDecimals","type":"uint8"},{"internalType":"address","name":"_lzEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"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":"_hash","type":"bytes32"}],"name":"CallOFTReceivedSuccess","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":false,"internalType":"address","name":"_address","type":"address"}],"name":"NonContractAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","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":"bytes32","name":"_toAddress","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBp","type":"uint16"}],"name":"SetDefaultFeeBp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"dstchainId","type":"uint16"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"},{"indexed":false,"internalType":"uint16","name":"feeBp","type":"uint16"}],"name":"SetFeeBp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeOwner","type":"address"}],"name":"SetFeeOwner","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":"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"},{"inputs":[],"name":"BP_DENOMINATOR","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":"NO_EXTRA_GAS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PT_SEND","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PT_SEND_AND_CALL","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes32","name":"_from","type":"bytes32"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint256","name":"_gasForCall","type":"uint256"}],"name":"callOnOFTReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"chainIdToFeeBps","outputs":[{"internalType":"uint16","name":"feeBP","type":"uint16"},{"internalType":"bool","name":"enabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"circulatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"creditedPackets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultFeeBp","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint64","name":"_dstGasForCall","type":"uint64"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendAndCallFee","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":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","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":[],"name":"feeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"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":"uint16","name":"_remoteChainId","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"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":[{"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":[],"name":"outboundAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"quoteOFTFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minAmount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint64","name":"_dstGasForCall","type":"uint64"},{"components":[{"internalType":"address payable","name":"refundAddress","type":"address"},{"internalType":"address","name":"zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"adapterParams","type":"bytes"}],"internalType":"struct ICommonOFT.LzCallParams","name":"_callParams","type":"tuple"}],"name":"sendAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes32","name":"_toAddress","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minAmount","type":"uint256"},{"components":[{"internalType":"address payable","name":"refundAddress","type":"address"},{"internalType":"address","name":"zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"adapterParams","type":"bytes"}],"internalType":"struct ICommonOFT.LzCallParams","name":"_callParams","type":"tuple"}],"name":"sendFrom","outputs":[],"stateMutability":"payable","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":"_feeBp","type":"uint16"}],"name":"setDefaultFeeBp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bool","name":"_enabled","type":"bool"},{"internalType":"uint16","name":"_feeBp","type":"uint16"}],"name":"setFeeBp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeOwner","type":"address"}],"name":"setFeeOwner","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":"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":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","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":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"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":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b506040516200498f3803806200498f8339810160408190526200003591620002c6565b818181818080620000463362000247565b6001600160a01b0316608052505060ff1660a0526200006d6000546001600160a01b031690565b600880546001600160a01b03928316620100000262010000600160b01b0319909116179055851660c081905260408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009450849350620000d6919062000310565b600060405180830381855afa9150503d806000811462000113576040519150601f19603f3d011682016040523d82523d6000602084013e62000118565b606091505b509150915081620001865760405162461bcd60e51b815260206004820152602d60248201527f50726f78794f4654576974684665653a206661696c656420746f20676574207460448201526c6f6b656e20646563696d616c7360981b60648201526084015b60405180910390fd5b6000818060200190518101906200019e919062000341565b90508060ff168560ff1611156200021e5760405162461bcd60e51b815260206004820152603360248201527f50726f78794f4654576974684665653a20736861726564446563696d616c732060448201527f6d757374206265203c3d20646563696d616c730000000000000000000000000060648201526084016200017d565b6200022a85826200037c565b6200023790600a6200049b565b60e05250620004ac945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620002af57600080fd5b919050565b805160ff81168114620002af57600080fd5b600080600060608486031215620002dc57600080fd5b620002e78462000297565b9250620002f760208501620002b4565b9150620003076040850162000297565b90509250925092565b6000825160005b8181101562000333576020818601810151858301520162000317565b506000920191825250919050565b6000602082840312156200035457600080fd5b6200035f82620002b4565b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111562000398576200039862000366565b92915050565b600181815b80851115620003df578160001904821115620003c357620003c362000366565b80851615620003d157918102915b93841c9390800290620003a3565b509250929050565b600082620003f85750600162000398565b81620004075750600062000398565b81600181146200042057600281146200042b576200044b565b600191505062000398565b60ff8411156200043f576200043f62000366565b50506001821b62000398565b5060208310610133831016604e8410600b841016171562000470575081810a62000398565b6200047c83836200039e565b806000190482111562000493576200049362000366565b029392505050565b60006200035f60ff841683620003e7565b60805160a05160c05160e0516144326200055d600039600081816126df0152818161287e0152612ee001526000818161092c015281816113580152818161234f015281816123d9015281816124120152818161245b01526127b4015260006105780152600081816107290152818161095301528181610bd901528181610c8101528181610e9c0152818161167601528181611c1601528181611f040152818161229d0152612a2501526144326000f3fe6080604052600436106102875760003560e01c80639358928b1161015a578063c83330ce116100c1578063eaffd49a1161007a578063eaffd49a1461087d578063eb8d72b71461089d578063ecd8f212146108bd578063f2fde38b146108dd578063f5ecbdbc146108fd578063fc0c546a1461091d57600080fd5b8063c83330ce14610791578063cbed8b9c146107e7578063d1deba1f14610807578063d88829681461081a578063df2a5b3b14610848578063e6a20ae61461086857600080fd5b8063a6c3d16511610113578063a6c3d165146106e1578063abe685cd14610701578063b353aaa714610717578063b9818be11461074b578063baf3292d14610771578063c44618341461070157600080fd5b80639358928b14610604578063950c8a74146106195780639689cb05146106395780639bdb98121461064f5780639f38369a146106a1578063a4c51df5146106c157600080fd5b8063455ba27d116101fe578063715018a6116101b7578063715018a6146105045780637533d7881461051957806379c0ad4b14610546578063857749b0146105665780638cfd8f5c1461059a5780638da5cb5b146105d257600080fd5b8063455ba27d1461041b5780634b104eff1461042e5780634c42899a1461044e5780635a359dc5146104755780635b8c41e61461049557806366ad5c8a146104e457600080fd5b80632cdf0b95116102505780632cdf0b9514610343578063365260b4146103565780633d8b38f61461038b5780633f1f4fa4146103ab57806342d65a8d146103e6578063447705151461040657600080fd5b80621d35671461028c57806301ffc9a7146102ae57806307e0db17146102e35780630df374831461030357806310ddb13714610323575b600080fd5b34801561029857600080fd5b506102ac6102a7366004613484565b610950565b005b3480156102ba57600080fd5b506102ce6102c9366004613517565b610b81565b60405190151581526020015b60405180910390f35b3480156102ef57600080fd5b506102ac6102fe366004613541565b610bb8565b34801561030f57600080fd5b506102ac61031e36600461355c565b610c41565b34801561032f57600080fd5b506102ac61033e366004613541565b610c60565b6102ac6103513660046135b3565b610cb8565b34801561036257600080fd5b5061037661037136600461363c565b610d5b565b604080519283526020830191909152016102da565b34801561039757600080fd5b506102ce6103a63660046136a3565b610db0565b3480156103b757600080fd5b506103d86103c6366004613541565b60036020526000908152604090205481565b6040519081526020016102da565b3480156103f257600080fd5b506102ac6104013660046136a3565b610e7d565b34801561041257600080fd5b506103d8600081565b6102ac6104293660046136f5565b610f03565b34801561043a57600080fd5b506102ac6104493660046137b1565b610fe4565b34801561045a57600080fd5b50610463600081565b60405160ff90911681526020016102da565b34801561048157600080fd5b506102ac610490366004613541565b6110a1565b3480156104a157600080fd5b506103d86104b036600461383b565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156104f057600080fd5b506102ac6104ff366004613484565b611113565b34801561051057600080fd5b506102ac6111e7565b34801561052557600080fd5b50610539610534366004613541565b6111fb565b6040516102da919061392b565b34801561055257600080fd5b506102ac61056136600461393e565b611295565b34801561057257600080fd5b506104637f000000000000000000000000000000000000000000000000000000000000000081565b3480156105a657600080fd5b506103d86105b536600461397a565b600260209081526000928352604080842090915290825290205481565b3480156105de57600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020016102da565b34801561061057600080fd5b506103d8611351565b34801561062557600080fd5b506004546105ec906001600160a01b031681565b34801561064557600080fd5b506103d860095481565b34801561065b57600080fd5b506102ce61066a36600461383b565b6006602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205460ff1681565b3480156106ad57600080fd5b506105396106bc366004613541565b6113e7565b3480156106cd57600080fd5b506103766106dc3660046139ad565b6114f6565b3480156106ed57600080fd5b506102ac6106fc3660046136a3565b611585565b34801561070d57600080fd5b506103d861271081565b34801561072357600080fd5b506105ec7f000000000000000000000000000000000000000000000000000000000000000081565b34801561075757600080fd5b506008546105ec906201000090046001600160a01b031681565b34801561077d57600080fd5b506102ac61078c3660046137b1565b611601565b34801561079d57600080fd5b506107cd6107ac366004613541565b60076020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102da565b3480156107f357600080fd5b506102ac610802366004613a6a565b611657565b6102ac610815366004613484565b6116e1565b34801561082657600080fd5b506008546108359061ffff1681565b60405161ffff90911681526020016102da565b34801561085457600080fd5b506102ac610863366004613ad8565b6118f7565b34801561087457600080fd5b50610463600181565b34801561088957600080fd5b506102ac610898366004613b14565b611961565b3480156108a957600080fd5b506102ac6108b83660046136a3565b611a80565b3480156108c957600080fd5b506103d86108d836600461355c565b611ada565b3480156108e957600080fd5b506102ac6108f83660046137b1565b611b6c565b34801561090957600080fd5b50610539610918366004613bdc565b611be5565b34801561092957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006105ec565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146109cd5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff8616600090815260016020526040812080546109eb90613c29565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1790613c29565b8015610a645780601f10610a3957610100808354040283529160200191610a64565b820191906000526020600020905b815481529060010190602001808311610a4757829003601f168201915b50505050509050805186869050148015610a7f575060008151115b8015610aa7575080516020820120604051610a9d9088908890613c5d565b6040518091039020145b610b025760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b60648201526084016109c4565b610b788787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250611c9892505050565b50505050505050565b60006001600160e01b03198216630d30953d60e31b1480610bb257506301ffc9a760e01b6001600160e01b03198316145b92915050565b610bc0611d11565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b5050505050565b610c49611d11565b61ffff909116600090815260036020526040902055565b610c68611d11565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610c0c565b610cc3868685611d6b565b509250610d3186868686610cda60208701876137b1565b610cea60408801602089016137b1565b610cf76040890189613c6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611db492505050565b925081831015610d535760405162461bcd60e51b81526004016109c490613cb3565b505050505050565b600080610da18888888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ed892505050565b91509150965096945050505050565b61ffff831660009081526001602052604081208054829190610dd190613c29565b80601f0160208091040260200160405190810160405280929190818152602001828054610dfd90613c29565b8015610e4a5780601f10610e1f57610100808354040283529160200191610e4a565b820191906000526020600020905b815481529060010190602001808311610e2d57829003601f168201915b505050505090508383604051610e61929190613c5d565b60405180910390208180519060200120149150505b9392505050565b610e85611d11565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d90610ed590869086908690600401613d29565b600060405180830381600087803b158015610eef57600080fd5b505af1158015610b78573d6000803e3d6000fd5b610f0e898988611d6b565b5080965050610fb78989898988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250610f6091505060208901896137b1565b610f7060408a0160208b016137b1565b610f7d60408b018b613c6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f9092505050565b955084861015610fd95760405162461bcd60e51b81526004016109c490613cb3565b505050505050505050565b610fec611d11565b6001600160a01b0381166110425760405162461bcd60e51b815260206004820152601a60248201527f4665653a206665654f776e65722063616e6e6f7420626520307800000000000060448201526064016109c4565b6008805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040519081527f047912631afa564eebd3db2efe191a0dec62da1fede6bbbc1ffc89d87845b1b5906020015b60405180910390a150565b6110a9611d11565b6127108161ffff1611156110cf5760405162461bcd60e51b81526004016109c490613d47565b6008805461ffff191661ffff83169081179091556040519081527fd26030ef4a8c225ee12b646eb4466acb41fb96b6cd4660b22d0ba0124e7bdc7490602001611096565b3330146111715760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b60648201526084016109c4565b610d538686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f89018190048102820181019092528781528993509150879087908190840183828082843760009201919091525061208c92505050565b6111ef611d11565b6111f96000612113565b565b6001602052600090815260409020805461121490613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461124090613c29565b801561128d5780601f106112625761010080835404028352916020019161128d565b820191906000526020600020905b81548152906001019060200180831161127057829003601f168201915b505050505081565b61129d611d11565b6127108161ffff1611156112c35760405162461bcd60e51b81526004016109c490613d47565b60408051808201825261ffff83811680835285151560208085018281528985166000818152600784528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820192909252918201527fdd9c9685af3e6dcb56d8f4b88d2595d4add6837a150034e7781c46b6dcf8aaab906060015b60405180910390a1505050565b60006009547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d89190613d8c565b6113e29190613dbb565b905090565b61ffff811660009081526001602052604081208054606092919061140a90613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461143690613c29565b80156114835780601f1061145857610100808354040283529160200191611483565b820191906000526020600020905b81548152906001019060200180831161146657829003601f168201915b5050505050905080516000036114db5760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f726400000060448201526064016109c4565b610e766000601483516114ee9190613dbb565b839190612163565b6000806115738b8b8b8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b81528e93508d9250908c908c908190840183828082843760009201919091525061227092505050565b91509150995099975050505050505050565b61158d611d11565b8181306040516020016115a293929190613dce565b60408051601f1981840301815291815261ffff85166000908152600160205220906115cd9082613e3a565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce83838360405161134493929190613d29565b611609611d11565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611096565b61165f611d11565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c906116b39088908890889088908890600401613ef9565b600060405180830381600087803b1580156116cd57600080fd5b505af1158015610fd9573d6000803e3d6000fd5b61ffff861660009081526005602052604080822090516117049088908890613c5d565b90815260408051602092819003830190206001600160401b038716600090815292529020549050806117845760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b60648201526084016109c4565b808383604051611795929190613c5d565b6040518091039020146117f45760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b60648201526084016109c4565b61ffff871660009081526005602052604080822090516118179089908990613c5d565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f880182900482028301820190528682526118af918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061208c92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516118e6959493929190613f27565b60405180910390a150505050505050565b6118ff611d11565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611344565b3330146119b05760405162461bcd60e51b815260206004820152601f60248201527f4f4654436f72653a2063616c6c6572206d757374206265204f4654436f72650060448201526064016109c4565b6119bb30868661232b565b9350846001600160a01b03168a61ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf866040516119fd91815260200190565b60405180910390a3604051633fe79aed60e11b81526001600160a01b03861690637fcf35da908390611a41908e908e908e908e908e908d908d908d90600401613f62565b600060405180830381600088803b158015611a5b57600080fd5b5087f1158015611a6f573d6000803e3d6000fd5b505050505050505050505050505050565b611a88611d11565b61ffff83166000908152600160205260409020611aa6828483613fbd565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab83838360405161134493929190613d29565b61ffff828116600090815260076020908152604080832081518083019092525493841681526201000090930460ff1615801591840191909152909190611b3f57805161271090611b2e9061ffff168561407c565b611b3891906140a9565b9150611b65565b60085461ffff1615611b605760085461271090611b2e9061ffff168561407c565b600091505b5092915050565b611b74611d11565b6001600160a01b038116611bd95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109c4565b611be281612113565b50565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc90608401600060405180830381865afa158015611c65573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c8d91908101906140bd565b90505b949350505050565b600080611cfb5a60966366ad5c8a60e01b89898989604051602401611cc0949392919061412a565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152309291906124db565b9150915081610d5357610d538686868685612565565b6000546001600160a01b031633146111f95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109c4565b600080611d788484611ada565b9050611d848184613dbb565b91508015611dac57600854611daa9086906201000090046001600160a01b03168361232b565b505b935093915050565b6000611dc287828481612602565b611dcb856126d7565b509050611dda88888884612717565b905060008111611e285760405162461bcd60e51b815260206004820152601960248201527813d19510dbdc994e88185b5bdd5b9d081d1bdbc81cdb585b1b603a1b60448201526064016109c4565b6000611e7387611e3784612876565b6040805160006020820152602181019390935260c09190911b6001600160c01b0319166041830152805160298184030181526049909201905290565b9050611e838882878787346128fc565b86896001600160a01b03168961ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051611ec491815260200190565b60405180910390a450979650505050505050565b6000806000611eea87611e3788612876565b60405163040a7bb160e41b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb1090611f41908b90309086908b908b90600401614168565b6040805180830381865afa158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8191906141bc565b92509250509550959350505050565b6000611fa8896001846001600160401b038916612602565b611fb1876126d7565b509050611fc08a8a8a84612717565b90506000811161200e5760405162461bcd60e51b815260206004820152601960248201527813d19510dbdc994e88185b5bdd5b9d081d1bdbc81cdb585b1b603a1b60448201526064016109c4565b6000612025338a61201e85612876565b8a8a612aa1565b90506120358a82878787346128fc565b888b6001600160a01b03168b61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a8560405161207691815260200190565b60405180910390a4509998505050505050505050565b60006120988282612ae2565b905060ff81166120b3576120ae85858585612b3e565b610c3a565b60001960ff8216016120cb576120ae85858585612bce565b60405162461bcd60e51b815260206004820152601c60248201527f4f4654436f72653a20756e6b6e6f776e207061636b657420747970650000000060448201526064016109c4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60608161217181601f6141e0565b10156121b05760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016109c4565b6121ba82846141e0565b845110156121fe5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016109c4565b60608215801561221d5760405191506000825260208201604052612267565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561225657805183526020928301920161223e565b5050858452601f01601f1916604052505b50949350505050565b6000806000612283338a61201e8b612876565b60405163040a7bb160e41b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb10906122da908d90309086908b908b90600401614168565b6040805180830381865afa1580156122f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231a91906141bc565b925092505097509795505050505050565b6040516370a0823160e01b81526001600160a01b03838116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190613d8c565b9050306001600160a01b03861603612405576124006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168585612ddd565b61243a565b61243a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016868686612e45565b6040516370a0823160e01b81526001600160a01b03858116600483015282917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa1580156124a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c89190613d8c565b6124d29190613dbb565b95945050505050565b6000606060008060008661ffff166001600160401b03811115612500576125006137ce565b6040519080825280601f01601f19166020018201604052801561252a576020820181803683370190505b50905060008087516020890160008d8df191503d92508683111561254c578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161259691906141f3565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906125f3908790879087908790879061420f565b60405180910390a15050505050565b600061260d83612e7d565b61ffff8087166000908152600260209081526040808320938916835292905220549091508061267e5760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f742073657400000000000060448201526064016109c4565b61268883826141e0565b821015610d535760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f77000000000060448201526064016109c4565b6000806127047f000000000000000000000000000000000000000000000000000000000000000084614261565b90506127108184613dbb565b9150915091565b60006001600160a01b03851633146127835760405162461bcd60e51b815260206004820152602960248201527f50726f78794f4654576974684665653a206f776e6572206973206e6f7420736560448201526837321031b0b63632b960b91b60648201526084016109c4565b61278e85308461232b565b915060008061279c846126d7565b909250905080156127db576127db6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168883612ddd565b81600960008282546127ed91906141e0565b90915550600090506128056001600160401b03612ed9565b905060095481101561286a5760405162461bcd60e51b815260206004820152602860248201527f50726f78794f4654576974684665653a206f7574626f756e64416d6f756e74206044820152676f766572666c6f7760c01b60648201526084016109c4565b50909695505050505050565b6000806128a37f0000000000000000000000000000000000000000000000000000000000000000846140a9565b90506001600160401b03811115610bb25760405162461bcd60e51b815260206004820152601a60248201527f4f4654436f72653a20616d6f756e745344206f766572666c6f7700000000000060448201526064016109c4565b61ffff86166000908152600160205260408120805461291a90613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461294690613c29565b80156129935780601f1061296857610100808354040283529160200191612993565b820191906000526020600020905b81548152906001019060200180831161297657829003601f168201915b505050505090508051600003612a045760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b60648201526084016109c4565b612a0f878751612f0e565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c5803100908490612a66908b9086908c908c908c908c90600401614275565b6000604051808303818588803b158015612a7f57600080fd5b505af1158015612a93573d6000803e3d6000fd5b505050505050505050505050565b6060600185856001600160a01b0389168587604051602001612ac8969594939291906142dc565b604051602081830303815290604052905095945050505050565b6000612aef8260016141e0565b83511015612b355760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b60448201526064016109c4565b50016001015190565b600080612b4a83612f7f565b90925090506001600160a01b038216612b635761dead91505b6000612b6e82612ed9565b9050612b7b878483613004565b9050826001600160a01b03168761ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf83604051612bbd91815260200190565b60405180910390a350505050505050565b6000806000806000612bdf8661303f565b945094509450945094506000600660008b61ffff1661ffff16815260200190815260200160002089604051612c1491906141f3565b90815260408051602092819003830190206001600160401b038b166000908152925281205460ff169150612c4785612ed9565b905081612cb557612c598b3083613004565b61ffff8c16600090815260066020526040908190209051919250600191612c81908d906141f3565b90815260408051602092819003830190206001600160401b038d16600090815292529020805460ff19169115159190911790555b6001600160a01b0386163b612d0c576040516001600160a01b03871681527f9aedf5fdba8716db3b6705ca00150643309995d4f818a249ed6dde6677e7792d9060200160405180910390a150505050505050612dd7565b8a8a8a8a8a8a868a60008a612d2a578b6001600160401b0316612d2c565b5a5b9050600080612d5e5a609663eaffd49a60e01b8e8e8e8d8d8d8d8d604051602401611cc098979695949392919061433d565b915091508115612db7578751602089012060405161ffff8d16907fb8890edbfc1c74692f527444645f95489c3703cc2df42e4a366f5d06fa6cd88490612da9908e908e9086906143b1565b60405180910390a250612dc4565b612dc48b8b8b8b85612565565b5050505050505050505050505050505050505b50505050565b6040516001600160a01b038316602482015260448101829052612e4090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526130f6565b505050565b6040516001600160a01b0380851660248301528316604482015260648101829052612dd79085906323b872dd60e01b90608401612e09565b6000602282511015612ed15760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d730000000060448201526064016109c4565b506022015190565b6000610bb27f00000000000000000000000000000000000000000000000000000000000000006001600160401b03841661407c565b61ffff821660009081526003602052604081205490819003612f2f57506127105b80821115612e405760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c6172676560448201526064016109c4565b60008080612f8d8482612ae2565b60ff16148015612f9e575082516029145b612fe55760405162461bcd60e51b815260206004820152601860248201527713d19510dbdc994e881a5b9d985b1a59081c185e5b1bd85960421b60448201526064016109c4565b612ff083600d6131cb565b9150612ffd836021613230565b9050915091565b600081600960008282546130189190613dbb565b9091555050306001600160a01b03841603613034575080610e76565b611c9030848461232b565b6000808060608160016130528783612ae2565b60ff161461309d5760405162461bcd60e51b815260206004820152601860248201527713d19510dbdc994e881a5b9d985b1a59081c185e5b1bd85960421b60448201526064016109c4565b6130a886600d6131cb565b93506130b5866021613230565b92506130c286602961328d565b94506130cf866049613230565b90506130eb60518088516130e39190613dbb565b889190612163565b915091939590929450565b600061314b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132eb9092919063ffffffff16565b905080516000148061316c57508080602001905181019061316c91906143df565b612e405760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109c4565b60006131d88260146141e0565b835110156132205760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b60448201526064016109c4565b500160200151600160601b900490565b600061323d8260086141e0565b835110156132845760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b60448201526064016109c4565b50016008015190565b600061329a8260206141e0565b835110156132e25760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b60448201526064016109c4565b50016020015190565b6060611c90848460008585600080866001600160a01b0316858760405161331291906141f3565b60006040518083038185875af1925050503d806000811461334f576040519150601f19603f3d011682016040523d82523d6000602084013e613354565b606091505b509150915061336587838387613370565b979650505050505050565b606083156133df5782516000036133d8576001600160a01b0385163b6133d85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109c4565b5081611c90565b611c9083838151156133f45781518083602001fd5b8060405162461bcd60e51b81526004016109c4919061392b565b803561ffff8116811461342057600080fd5b919050565b60008083601f84011261343757600080fd5b5081356001600160401b0381111561344e57600080fd5b60208301915083602082850101111561346657600080fd5b9250929050565b80356001600160401b038116811461342057600080fd5b6000806000806000806080878903121561349d57600080fd5b6134a68761340e565b955060208701356001600160401b03808211156134c257600080fd5b6134ce8a838b01613425565b90975095508591506134e260408a0161346d565b945060608901359150808211156134f857600080fd5b5061350589828a01613425565b979a9699509497509295939492505050565b60006020828403121561352957600080fd5b81356001600160e01b031981168114610e7657600080fd5b60006020828403121561355357600080fd5b610e768261340e565b6000806040838503121561356f57600080fd5b6135788361340e565b946020939093013593505050565b6001600160a01b0381168114611be257600080fd5b6000606082840312156135ad57600080fd5b50919050565b60008060008060008060c087890312156135cc57600080fd5b86356135d781613586565b95506135e56020880161340e565b945060408701359350606087013592506080870135915060a08701356001600160401b0381111561361557600080fd5b61362189828a0161359b565b9150509295509295509295565b8015158114611be257600080fd5b60008060008060008060a0878903121561365557600080fd5b61365e8761340e565b95506020870135945060408701359350606087013561367c8161362e565b925060808701356001600160401b0381111561369757600080fd5b61350589828a01613425565b6000806000604084860312156136b857600080fd5b6136c18461340e565b925060208401356001600160401b038111156136dc57600080fd5b6136e886828701613425565b9497909650939450505050565b60008060008060008060008060006101008a8c03121561371457600080fd5b893561371f81613586565b985061372d60208b0161340e565b975060408a0135965060608a0135955060808a0135945060a08a01356001600160401b038082111561375e57600080fd5b61376a8d838e01613425565b909650945084915061377e60c08d0161346d565b935060e08c013591508082111561379457600080fd5b506137a18c828d0161359b565b9150509295985092959850929598565b6000602082840312156137c357600080fd5b8135610e7681613586565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561380c5761380c6137ce565b604052919050565b60006001600160401b0382111561382d5761382d6137ce565b50601f01601f191660200190565b60008060006060848603121561385057600080fd5b6138598461340e565b925060208401356001600160401b0381111561387457600080fd5b8401601f8101861361388557600080fd5b803561389861389382613814565b6137e4565b8181528760208385010111156138ad57600080fd5b816020840160208301376000602083830101528094505050506138d26040850161346d565b90509250925092565b60005b838110156138f65781810151838201526020016138de565b50506000910152565b600081518084526139178160208601602086016138db565b601f01601f19169290920160200192915050565b602081526000610e7660208301846138ff565b60008060006060848603121561395357600080fd5b61395c8461340e565b9250602084013561396c8161362e565b91506138d26040850161340e565b6000806040838503121561398d57600080fd5b6139968361340e565b91506139a46020840161340e565b90509250929050565b600080600080600080600080600060e08a8c0312156139cb57600080fd5b6139d48a61340e565b985060208a0135975060408a0135965060608a01356001600160401b03808211156139fe57600080fd5b613a0a8d838e01613425565b9098509650869150613a1e60808d0161346d565b955060a08c01359150613a308261362e565b90935060c08b01359080821115613a4657600080fd5b50613a538c828d01613425565b915080935050809150509295985092959850929598565b600080600080600060808688031215613a8257600080fd5b613a8b8661340e565b9450613a996020870161340e565b93506040860135925060608601356001600160401b03811115613abb57600080fd5b613ac788828901613425565b969995985093965092949392505050565b600080600060608486031215613aed57600080fd5b613af68461340e565b9250613b046020850161340e565b9150604084013590509250925092565b6000806000806000806000806000806101008b8d031215613b3457600080fd5b613b3d8b61340e565b995060208b01356001600160401b0380821115613b5957600080fd5b613b658e838f01613425565b909b509950899150613b7960408e0161346d565b985060608d0135975060808d01359150613b9282613586565b90955060a08c0135945060c08c01359080821115613baf57600080fd5b50613bbc8d828e01613425565b9150809450508092505060e08b013590509295989b9194979a5092959850565b60008060008060808587031215613bf257600080fd5b613bfb8561340e565b9350613c096020860161340e565b92506040850135613c1981613586565b9396929550929360600135925050565b600181811c90821680613c3d57607f821691505b6020821081036135ad57634e487b7160e01b600052602260045260246000fd5b8183823760009101908152919050565b6000808335601e19843603018112613c8457600080fd5b8301803591506001600160401b03821115613c9e57600080fd5b60200191503681900382131561346657600080fd5b6020808252602d908201527f426173654f4654576974684665653a20616d6f756e74206973206c657373207460408201526c1a185b881b5a5b905b5bdd5b9d609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff84168152604060208201526000611c8d604083018486613d00565b60208082526025908201527f4665653a20666565206270206d757374206265203c3d2042505f44454e4f4d496040820152642720aa27a960d91b606082015260800190565b600060208284031215613d9e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610bb257610bb2613da5565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f821115612e4057600081815260208120601f850160051c81016020861015613e1b5750805b601f850160051c820191505b81811015610d5357828155600101613e27565b81516001600160401b03811115613e5357613e536137ce565b613e6781613e618454613c29565b84613df4565b602080601f831160018114613e9c5760008415613e845750858301515b600019600386901b1c1916600185901b178555610d53565b600085815260208120601f198616915b82811015613ecb57888601518255948401946001909101908401613eac565b5085821015613ee95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600061ffff808816835280871660208401525084604083015260806060830152613365608083018486613d00565b61ffff86168152608060208201526000613f45608083018688613d00565b6001600160401b0394909416604083015250606001529392505050565b61ffff8916815260c060208201526000613f8060c08301898b613d00565b6001600160401b038816604084015286606084015285608084015282810360a0840152613fae818587613d00565b9b9a5050505050505050505050565b6001600160401b03831115613fd457613fd46137ce565b613fe883613fe28354613c29565b83613df4565b6000601f84116001811461401c57600085156140045750838201355b600019600387901b1c1916600186901b178355610c3a565b600083815260209020601f19861690835b8281101561404d578685013582556020948501946001909201910161402d565b508682101561406a5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8082028115828204841417610bb257610bb2613da5565b634e487b7160e01b600052601260045260246000fd5b6000826140b8576140b8614093565b500490565b6000602082840312156140cf57600080fd5b81516001600160401b038111156140e557600080fd5b8201601f810184136140f657600080fd5b805161410461389382613814565b81815285602083850101111561411957600080fd5b6124d28260208301602086016138db565b61ffff8516815260806020820152600061414760808301866138ff565b6001600160401b0385166040840152828103606084015261336581856138ff565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614196908301866138ff565b841515606084015282810360808401526141b081856138ff565b98975050505050505050565b600080604083850312156141cf57600080fd5b505080516020909101519092909150565b80820180821115610bb257610bb2613da5565b600082516142058184602087016138db565b9190910192915050565b61ffff8616815260a06020820152600061422c60a08301876138ff565b6001600160401b0386166040840152828103606084015261424d81866138ff565b905082810360808401526141b081856138ff565b60008261427057614270614093565b500690565b61ffff8716815260c06020820152600061429260c08301886138ff565b82810360408401526142a481886138ff565b6001600160a01b0387811660608601528616608085015283810360a085015290506142cf81856138ff565b9998505050505050505050565b60ff60f81b8760f81b16815285600182015260006001600160401b0360c01b808760c01b166021840152856029840152808560c01b16604984015250825161432b8160518501602087016138db565b91909101605101979650505050505050565b600061010061ffff8b16835280602084015261435b8184018b6138ff565b6001600160401b038a166040850152606084018990526001600160a01b038816608085015260a0840187905283810360c0850152905061439b81866138ff565b9150508260e08301529998505050505050505050565b6060815260006143c460608301866138ff565b6001600160401b039490941660208301525060400152919050565b6000602082840312156143f157600080fd5b8151610e768161362e56fea26469706673582212204495807a73f54df216e7031f0d93c92bdc992182a5b4b976b789686dedbed27264736f6c63430008140033000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9000000000000000000000000000000000000000000000000000000000000000800000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675

Deployed Bytecode

0x6080604052600436106102875760003560e01c80639358928b1161015a578063c83330ce116100c1578063eaffd49a1161007a578063eaffd49a1461087d578063eb8d72b71461089d578063ecd8f212146108bd578063f2fde38b146108dd578063f5ecbdbc146108fd578063fc0c546a1461091d57600080fd5b8063c83330ce14610791578063cbed8b9c146107e7578063d1deba1f14610807578063d88829681461081a578063df2a5b3b14610848578063e6a20ae61461086857600080fd5b8063a6c3d16511610113578063a6c3d165146106e1578063abe685cd14610701578063b353aaa714610717578063b9818be11461074b578063baf3292d14610771578063c44618341461070157600080fd5b80639358928b14610604578063950c8a74146106195780639689cb05146106395780639bdb98121461064f5780639f38369a146106a1578063a4c51df5146106c157600080fd5b8063455ba27d116101fe578063715018a6116101b7578063715018a6146105045780637533d7881461051957806379c0ad4b14610546578063857749b0146105665780638cfd8f5c1461059a5780638da5cb5b146105d257600080fd5b8063455ba27d1461041b5780634b104eff1461042e5780634c42899a1461044e5780635a359dc5146104755780635b8c41e61461049557806366ad5c8a146104e457600080fd5b80632cdf0b95116102505780632cdf0b9514610343578063365260b4146103565780633d8b38f61461038b5780633f1f4fa4146103ab57806342d65a8d146103e6578063447705151461040657600080fd5b80621d35671461028c57806301ffc9a7146102ae57806307e0db17146102e35780630df374831461030357806310ddb13714610323575b600080fd5b34801561029857600080fd5b506102ac6102a7366004613484565b610950565b005b3480156102ba57600080fd5b506102ce6102c9366004613517565b610b81565b60405190151581526020015b60405180910390f35b3480156102ef57600080fd5b506102ac6102fe366004613541565b610bb8565b34801561030f57600080fd5b506102ac61031e36600461355c565b610c41565b34801561032f57600080fd5b506102ac61033e366004613541565b610c60565b6102ac6103513660046135b3565b610cb8565b34801561036257600080fd5b5061037661037136600461363c565b610d5b565b604080519283526020830191909152016102da565b34801561039757600080fd5b506102ce6103a63660046136a3565b610db0565b3480156103b757600080fd5b506103d86103c6366004613541565b60036020526000908152604090205481565b6040519081526020016102da565b3480156103f257600080fd5b506102ac6104013660046136a3565b610e7d565b34801561041257600080fd5b506103d8600081565b6102ac6104293660046136f5565b610f03565b34801561043a57600080fd5b506102ac6104493660046137b1565b610fe4565b34801561045a57600080fd5b50610463600081565b60405160ff90911681526020016102da565b34801561048157600080fd5b506102ac610490366004613541565b6110a1565b3480156104a157600080fd5b506103d86104b036600461383b565b6005602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b3480156104f057600080fd5b506102ac6104ff366004613484565b611113565b34801561051057600080fd5b506102ac6111e7565b34801561052557600080fd5b50610539610534366004613541565b6111fb565b6040516102da919061392b565b34801561055257600080fd5b506102ac61056136600461393e565b611295565b34801561057257600080fd5b506104637f000000000000000000000000000000000000000000000000000000000000000881565b3480156105a657600080fd5b506103d86105b536600461397a565b600260209081526000928352604080842090915290825290205481565b3480156105de57600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020016102da565b34801561061057600080fd5b506103d8611351565b34801561062557600080fd5b506004546105ec906001600160a01b031681565b34801561064557600080fd5b506103d860095481565b34801561065b57600080fd5b506102ce61066a36600461383b565b6006602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205460ff1681565b3480156106ad57600080fd5b506105396106bc366004613541565b6113e7565b3480156106cd57600080fd5b506103766106dc3660046139ad565b6114f6565b3480156106ed57600080fd5b506102ac6106fc3660046136a3565b611585565b34801561070d57600080fd5b506103d861271081565b34801561072357600080fd5b506105ec7f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67581565b34801561075757600080fd5b506008546105ec906201000090046001600160a01b031681565b34801561077d57600080fd5b506102ac61078c3660046137b1565b611601565b34801561079d57600080fd5b506107cd6107ac366004613541565b60076020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102da565b3480156107f357600080fd5b506102ac610802366004613a6a565b611657565b6102ac610815366004613484565b6116e1565b34801561082657600080fd5b506008546108359061ffff1681565b60405161ffff90911681526020016102da565b34801561085457600080fd5b506102ac610863366004613ad8565b6118f7565b34801561087457600080fd5b50610463600181565b34801561088957600080fd5b506102ac610898366004613b14565b611961565b3480156108a957600080fd5b506102ac6108b83660046136a3565b611a80565b3480156108c957600080fd5b506103d86108d836600461355c565b611ada565b3480156108e957600080fd5b506102ac6108f83660046137b1565b611b6c565b34801561090957600080fd5b50610539610918366004613bdc565b611be5565b34801561092957600080fd5b507f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb96105ec565b337f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b0316146109cd5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff8616600090815260016020526040812080546109eb90613c29565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1790613c29565b8015610a645780601f10610a3957610100808354040283529160200191610a64565b820191906000526020600020905b815481529060010190602001808311610a4757829003601f168201915b50505050509050805186869050148015610a7f575060008151115b8015610aa7575080516020820120604051610a9d9088908890613c5d565b6040518091039020145b610b025760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b60648201526084016109c4565b610b788787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a935091508890889081908401838280828437600092019190915250611c9892505050565b50505050505050565b60006001600160e01b03198216630d30953d60e31b1480610bb257506301ffc9a760e01b6001600160e01b03198316145b92915050565b610bc0611d11565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b5050505050565b610c49611d11565b61ffff909116600090815260036020526040902055565b610c68611d11565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b0316906310ddb13790602401610c0c565b610cc3868685611d6b565b509250610d3186868686610cda60208701876137b1565b610cea60408801602089016137b1565b610cf76040890189613c6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611db492505050565b925081831015610d535760405162461bcd60e51b81526004016109c490613cb3565b505050505050565b600080610da18888888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ed892505050565b91509150965096945050505050565b61ffff831660009081526001602052604081208054829190610dd190613c29565b80601f0160208091040260200160405190810160405280929190818152602001828054610dfd90613c29565b8015610e4a5780601f10610e1f57610100808354040283529160200191610e4a565b820191906000526020600020905b815481529060010190602001808311610e2d57829003601f168201915b505050505090508383604051610e61929190613c5d565b60405180910390208180519060200120149150505b9392505050565b610e85611d11565b6040516342d65a8d60e01b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67516906342d65a8d90610ed590869086908690600401613d29565b600060405180830381600087803b158015610eef57600080fd5b505af1158015610b78573d6000803e3d6000fd5b610f0e898988611d6b565b5080965050610fb78989898988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250610f6091505060208901896137b1565b610f7060408a0160208b016137b1565b610f7d60408b018b613c6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f9092505050565b955084861015610fd95760405162461bcd60e51b81526004016109c490613cb3565b505050505050505050565b610fec611d11565b6001600160a01b0381166110425760405162461bcd60e51b815260206004820152601a60248201527f4665653a206665654f776e65722063616e6e6f7420626520307800000000000060448201526064016109c4565b6008805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040519081527f047912631afa564eebd3db2efe191a0dec62da1fede6bbbc1ffc89d87845b1b5906020015b60405180910390a150565b6110a9611d11565b6127108161ffff1611156110cf5760405162461bcd60e51b81526004016109c490613d47565b6008805461ffff191661ffff83169081179091556040519081527fd26030ef4a8c225ee12b646eb4466acb41fb96b6cd4660b22d0ba0124e7bdc7490602001611096565b3330146111715760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b60648201526084016109c4565b610d538686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f89018190048102820181019092528781528993509150879087908190840183828082843760009201919091525061208c92505050565b6111ef611d11565b6111f96000612113565b565b6001602052600090815260409020805461121490613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461124090613c29565b801561128d5780601f106112625761010080835404028352916020019161128d565b820191906000526020600020905b81548152906001019060200180831161127057829003601f168201915b505050505081565b61129d611d11565b6127108161ffff1611156112c35760405162461bcd60e51b81526004016109c490613d47565b60408051808201825261ffff83811680835285151560208085018281528985166000818152600784528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820192909252918201527fdd9c9685af3e6dcb56d8f4b88d2595d4add6837a150034e7781c46b6dcf8aaab906060015b60405180910390a1505050565b60006009547f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb96001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d89190613d8c565b6113e29190613dbb565b905090565b61ffff811660009081526001602052604081208054606092919061140a90613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461143690613c29565b80156114835780601f1061145857610100808354040283529160200191611483565b820191906000526020600020905b81548152906001019060200180831161146657829003601f168201915b5050505050905080516000036114db5760405162461bcd60e51b815260206004820152601d60248201527f4c7a4170703a206e6f20747275737465642070617468207265636f726400000060448201526064016109c4565b610e766000601483516114ee9190613dbb565b839190612163565b6000806115738b8b8b8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b81528e93508d9250908c908c908190840183828082843760009201919091525061227092505050565b91509150995099975050505050505050565b61158d611d11565b8181306040516020016115a293929190613dce565b60408051601f1981840301815291815261ffff85166000908152600160205220906115cd9082613e3a565b507f8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ce83838360405161134493929190613d29565b611609611d11565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527f5db758e995a17ec1ad84bdef7e8c3293a0bd6179bcce400dff5d4c3d87db726b90602001611096565b61165f611d11565b6040516332fb62e760e21b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675169063cbed8b9c906116b39088908890889088908890600401613ef9565b600060405180830381600087803b1580156116cd57600080fd5b505af1158015610fd9573d6000803e3d6000fd5b61ffff861660009081526005602052604080822090516117049088908890613c5d565b90815260408051602092819003830190206001600160401b038716600090815292529020549050806117845760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b60648201526084016109c4565b808383604051611795929190613c5d565b6040518091039020146117f45760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b60648201526084016109c4565b61ffff871660009081526005602052604080822090516118179089908990613c5d565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f880182900482028301820190528682526118af918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061208c92505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516118e6959493929190613f27565b60405180910390a150505050505050565b6118ff611d11565b61ffff83811660008181526002602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611344565b3330146119b05760405162461bcd60e51b815260206004820152601f60248201527f4f4654436f72653a2063616c6c6572206d757374206265204f4654436f72650060448201526064016109c4565b6119bb30868661232b565b9350846001600160a01b03168a61ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf866040516119fd91815260200190565b60405180910390a3604051633fe79aed60e11b81526001600160a01b03861690637fcf35da908390611a41908e908e908e908e908e908d908d908d90600401613f62565b600060405180830381600088803b158015611a5b57600080fd5b5087f1158015611a6f573d6000803e3d6000fd5b505050505050505050505050505050565b611a88611d11565b61ffff83166000908152600160205260409020611aa6828483613fbd565b507ffa41487ad5d6728f0b19276fa1eddc16558578f5109fc39d2dc33c3230470dab83838360405161134493929190613d29565b61ffff828116600090815260076020908152604080832081518083019092525493841681526201000090930460ff1615801591840191909152909190611b3f57805161271090611b2e9061ffff168561407c565b611b3891906140a9565b9150611b65565b60085461ffff1615611b605760085461271090611b2e9061ffff168561407c565b600091505b5092915050565b611b74611d11565b6001600160a01b038116611bd95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109c4565b611be281612113565b50565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd6756001600160a01b03169063f5ecbdbc90608401600060405180830381865afa158015611c65573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c8d91908101906140bd565b90505b949350505050565b600080611cfb5a60966366ad5c8a60e01b89898989604051602401611cc0949392919061412a565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152309291906124db565b9150915081610d5357610d538686868685612565565b6000546001600160a01b031633146111f95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109c4565b600080611d788484611ada565b9050611d848184613dbb565b91508015611dac57600854611daa9086906201000090046001600160a01b03168361232b565b505b935093915050565b6000611dc287828481612602565b611dcb856126d7565b509050611dda88888884612717565b905060008111611e285760405162461bcd60e51b815260206004820152601960248201527813d19510dbdc994e88185b5bdd5b9d081d1bdbc81cdb585b1b603a1b60448201526064016109c4565b6000611e7387611e3784612876565b6040805160006020820152602181019390935260c09190911b6001600160c01b0319166041830152805160298184030181526049909201905290565b9050611e838882878787346128fc565b86896001600160a01b03168961ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a85604051611ec491815260200190565b60405180910390a450979650505050505050565b6000806000611eea87611e3788612876565b60405163040a7bb160e41b81529091506001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67516906340a7bb1090611f41908b90309086908b908b90600401614168565b6040805180830381865afa158015611f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8191906141bc565b92509250509550959350505050565b6000611fa8896001846001600160401b038916612602565b611fb1876126d7565b509050611fc08a8a8a84612717565b90506000811161200e5760405162461bcd60e51b815260206004820152601960248201527813d19510dbdc994e88185b5bdd5b9d081d1bdbc81cdb585b1b603a1b60448201526064016109c4565b6000612025338a61201e85612876565b8a8a612aa1565b90506120358a82878787346128fc565b888b6001600160a01b03168b61ffff167fd81fc9b8523134ed613870ed029d6170cbb73aa6a6bc311b9a642689fb9df59a8560405161207691815260200190565b60405180910390a4509998505050505050505050565b60006120988282612ae2565b905060ff81166120b3576120ae85858585612b3e565b610c3a565b60001960ff8216016120cb576120ae85858585612bce565b60405162461bcd60e51b815260206004820152601c60248201527f4f4654436f72653a20756e6b6e6f776e207061636b657420747970650000000060448201526064016109c4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60608161217181601f6141e0565b10156121b05760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b60448201526064016109c4565b6121ba82846141e0565b845110156121fe5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b60448201526064016109c4565b60608215801561221d5760405191506000825260208201604052612267565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561225657805183526020928301920161223e565b5050858452601f01601f1916604052505b50949350505050565b6000806000612283338a61201e8b612876565b60405163040a7bb160e41b81529091506001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd67516906340a7bb10906122da908d90309086908b908b90600401614168565b6040805180830381865afa1580156122f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231a91906141bc565b925092505097509795505050505050565b6040516370a0823160e01b81526001600160a01b03838116600483015260009182917f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb916906370a0823190602401602060405180830381865afa158015612396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ba9190613d8c565b9050306001600160a01b03861603612405576124006001600160a01b037f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9168585612ddd565b61243a565b61243a6001600160a01b037f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb916868686612e45565b6040516370a0823160e01b81526001600160a01b03858116600483015282917f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9909116906370a0823190602401602060405180830381865afa1580156124a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c89190613d8c565b6124d29190613dbb565b95945050505050565b6000606060008060008661ffff166001600160401b03811115612500576125006137ce565b6040519080825280601f01601f19166020018201604052801561252a576020820181803683370190505b50905060008087516020890160008d8df191503d92508683111561254c578692505b828152826000602083013e909890975095505050505050565b8180519060200120600560008761ffff1661ffff1681526020019081526020016000208560405161259691906141f3565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c906125f3908790879087908790879061420f565b60405180910390a15050505050565b600061260d83612e7d565b61ffff8087166000908152600260209081526040808320938916835292905220549091508061267e5760405162461bcd60e51b815260206004820152601a60248201527f4c7a4170703a206d696e4761734c696d6974206e6f742073657400000000000060448201526064016109c4565b61268883826141e0565b821015610d535760405162461bcd60e51b815260206004820152601b60248201527f4c7a4170703a20676173206c696d697420697320746f6f206c6f77000000000060448201526064016109c4565b6000806127047f00000000000000000000000000000000000000000000000000000002540be40084614261565b90506127108184613dbb565b9150915091565b60006001600160a01b03851633146127835760405162461bcd60e51b815260206004820152602960248201527f50726f78794f4654576974684665653a206f776e6572206973206e6f7420736560448201526837321031b0b63632b960b91b60648201526084016109c4565b61278e85308461232b565b915060008061279c846126d7565b909250905080156127db576127db6001600160a01b037f000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9168883612ddd565b81600960008282546127ed91906141e0565b90915550600090506128056001600160401b03612ed9565b905060095481101561286a5760405162461bcd60e51b815260206004820152602860248201527f50726f78794f4654576974684665653a206f7574626f756e64416d6f756e74206044820152676f766572666c6f7760c01b60648201526084016109c4565b50909695505050505050565b6000806128a37f00000000000000000000000000000000000000000000000000000002540be400846140a9565b90506001600160401b03811115610bb25760405162461bcd60e51b815260206004820152601a60248201527f4f4654436f72653a20616d6f756e745344206f766572666c6f7700000000000060448201526064016109c4565b61ffff86166000908152600160205260408120805461291a90613c29565b80601f016020809104026020016040519081016040528092919081815260200182805461294690613c29565b80156129935780601f1061296857610100808354040283529160200191612993565b820191906000526020600020905b81548152906001019060200180831161297657829003601f168201915b505050505090508051600003612a045760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b60648201526084016109c4565b612a0f878751612f0e565b60405162c5803160e81b81526001600160a01b037f00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675169063c5803100908490612a66908b9086908c908c908c908c90600401614275565b6000604051808303818588803b158015612a7f57600080fd5b505af1158015612a93573d6000803e3d6000fd5b505050505050505050505050565b6060600185856001600160a01b0389168587604051602001612ac8969594939291906142dc565b604051602081830303815290604052905095945050505050565b6000612aef8260016141e0565b83511015612b355760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b60448201526064016109c4565b50016001015190565b600080612b4a83612f7f565b90925090506001600160a01b038216612b635761dead91505b6000612b6e82612ed9565b9050612b7b878483613004565b9050826001600160a01b03168761ffff167fbf551ec93859b170f9b2141bd9298bf3f64322c6f7beb2543a0cb669834118bf83604051612bbd91815260200190565b60405180910390a350505050505050565b6000806000806000612bdf8661303f565b945094509450945094506000600660008b61ffff1661ffff16815260200190815260200160002089604051612c1491906141f3565b90815260408051602092819003830190206001600160401b038b166000908152925281205460ff169150612c4785612ed9565b905081612cb557612c598b3083613004565b61ffff8c16600090815260066020526040908190209051919250600191612c81908d906141f3565b90815260408051602092819003830190206001600160401b038d16600090815292529020805460ff19169115159190911790555b6001600160a01b0386163b612d0c576040516001600160a01b03871681527f9aedf5fdba8716db3b6705ca00150643309995d4f818a249ed6dde6677e7792d9060200160405180910390a150505050505050612dd7565b8a8a8a8a8a8a868a60008a612d2a578b6001600160401b0316612d2c565b5a5b9050600080612d5e5a609663eaffd49a60e01b8e8e8e8d8d8d8d8d604051602401611cc098979695949392919061433d565b915091508115612db7578751602089012060405161ffff8d16907fb8890edbfc1c74692f527444645f95489c3703cc2df42e4a366f5d06fa6cd88490612da9908e908e9086906143b1565b60405180910390a250612dc4565b612dc48b8b8b8b85612565565b5050505050505050505050505050505050505b50505050565b6040516001600160a01b038316602482015260448101829052612e4090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526130f6565b505050565b6040516001600160a01b0380851660248301528316604482015260648101829052612dd79085906323b872dd60e01b90608401612e09565b6000602282511015612ed15760405162461bcd60e51b815260206004820152601c60248201527f4c7a4170703a20696e76616c69642061646170746572506172616d730000000060448201526064016109c4565b506022015190565b6000610bb27f00000000000000000000000000000000000000000000000000000002540be4006001600160401b03841661407c565b61ffff821660009081526003602052604081205490819003612f2f57506127105b80821115612e405760405162461bcd60e51b815260206004820181905260248201527f4c7a4170703a207061796c6f61642073697a6520697320746f6f206c6172676560448201526064016109c4565b60008080612f8d8482612ae2565b60ff16148015612f9e575082516029145b612fe55760405162461bcd60e51b815260206004820152601860248201527713d19510dbdc994e881a5b9d985b1a59081c185e5b1bd85960421b60448201526064016109c4565b612ff083600d6131cb565b9150612ffd836021613230565b9050915091565b600081600960008282546130189190613dbb565b9091555050306001600160a01b03841603613034575080610e76565b611c9030848461232b565b6000808060608160016130528783612ae2565b60ff161461309d5760405162461bcd60e51b815260206004820152601860248201527713d19510dbdc994e881a5b9d985b1a59081c185e5b1bd85960421b60448201526064016109c4565b6130a886600d6131cb565b93506130b5866021613230565b92506130c286602961328d565b94506130cf866049613230565b90506130eb60518088516130e39190613dbb565b889190612163565b915091939590929450565b600061314b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132eb9092919063ffffffff16565b905080516000148061316c57508080602001905181019061316c91906143df565b612e405760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109c4565b60006131d88260146141e0565b835110156132205760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b60448201526064016109c4565b500160200151600160601b900490565b600061323d8260086141e0565b835110156132845760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b60448201526064016109c4565b50016008015190565b600061329a8260206141e0565b835110156132e25760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b60448201526064016109c4565b50016020015190565b6060611c90848460008585600080866001600160a01b0316858760405161331291906141f3565b60006040518083038185875af1925050503d806000811461334f576040519150601f19603f3d011682016040523d82523d6000602084013e613354565b606091505b509150915061336587838387613370565b979650505050505050565b606083156133df5782516000036133d8576001600160a01b0385163b6133d85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109c4565b5081611c90565b611c9083838151156133f45781518083602001fd5b8060405162461bcd60e51b81526004016109c4919061392b565b803561ffff8116811461342057600080fd5b919050565b60008083601f84011261343757600080fd5b5081356001600160401b0381111561344e57600080fd5b60208301915083602082850101111561346657600080fd5b9250929050565b80356001600160401b038116811461342057600080fd5b6000806000806000806080878903121561349d57600080fd5b6134a68761340e565b955060208701356001600160401b03808211156134c257600080fd5b6134ce8a838b01613425565b90975095508591506134e260408a0161346d565b945060608901359150808211156134f857600080fd5b5061350589828a01613425565b979a9699509497509295939492505050565b60006020828403121561352957600080fd5b81356001600160e01b031981168114610e7657600080fd5b60006020828403121561355357600080fd5b610e768261340e565b6000806040838503121561356f57600080fd5b6135788361340e565b946020939093013593505050565b6001600160a01b0381168114611be257600080fd5b6000606082840312156135ad57600080fd5b50919050565b60008060008060008060c087890312156135cc57600080fd5b86356135d781613586565b95506135e56020880161340e565b945060408701359350606087013592506080870135915060a08701356001600160401b0381111561361557600080fd5b61362189828a0161359b565b9150509295509295509295565b8015158114611be257600080fd5b60008060008060008060a0878903121561365557600080fd5b61365e8761340e565b95506020870135945060408701359350606087013561367c8161362e565b925060808701356001600160401b0381111561369757600080fd5b61350589828a01613425565b6000806000604084860312156136b857600080fd5b6136c18461340e565b925060208401356001600160401b038111156136dc57600080fd5b6136e886828701613425565b9497909650939450505050565b60008060008060008060008060006101008a8c03121561371457600080fd5b893561371f81613586565b985061372d60208b0161340e565b975060408a0135965060608a0135955060808a0135945060a08a01356001600160401b038082111561375e57600080fd5b61376a8d838e01613425565b909650945084915061377e60c08d0161346d565b935060e08c013591508082111561379457600080fd5b506137a18c828d0161359b565b9150509295985092959850929598565b6000602082840312156137c357600080fd5b8135610e7681613586565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561380c5761380c6137ce565b604052919050565b60006001600160401b0382111561382d5761382d6137ce565b50601f01601f191660200190565b60008060006060848603121561385057600080fd5b6138598461340e565b925060208401356001600160401b0381111561387457600080fd5b8401601f8101861361388557600080fd5b803561389861389382613814565b6137e4565b8181528760208385010111156138ad57600080fd5b816020840160208301376000602083830101528094505050506138d26040850161346d565b90509250925092565b60005b838110156138f65781810151838201526020016138de565b50506000910152565b600081518084526139178160208601602086016138db565b601f01601f19169290920160200192915050565b602081526000610e7660208301846138ff565b60008060006060848603121561395357600080fd5b61395c8461340e565b9250602084013561396c8161362e565b91506138d26040850161340e565b6000806040838503121561398d57600080fd5b6139968361340e565b91506139a46020840161340e565b90509250929050565b600080600080600080600080600060e08a8c0312156139cb57600080fd5b6139d48a61340e565b985060208a0135975060408a0135965060608a01356001600160401b03808211156139fe57600080fd5b613a0a8d838e01613425565b9098509650869150613a1e60808d0161346d565b955060a08c01359150613a308261362e565b90935060c08b01359080821115613a4657600080fd5b50613a538c828d01613425565b915080935050809150509295985092959850929598565b600080600080600060808688031215613a8257600080fd5b613a8b8661340e565b9450613a996020870161340e565b93506040860135925060608601356001600160401b03811115613abb57600080fd5b613ac788828901613425565b969995985093965092949392505050565b600080600060608486031215613aed57600080fd5b613af68461340e565b9250613b046020850161340e565b9150604084013590509250925092565b6000806000806000806000806000806101008b8d031215613b3457600080fd5b613b3d8b61340e565b995060208b01356001600160401b0380821115613b5957600080fd5b613b658e838f01613425565b909b509950899150613b7960408e0161346d565b985060608d0135975060808d01359150613b9282613586565b90955060a08c0135945060c08c01359080821115613baf57600080fd5b50613bbc8d828e01613425565b9150809450508092505060e08b013590509295989b9194979a5092959850565b60008060008060808587031215613bf257600080fd5b613bfb8561340e565b9350613c096020860161340e565b92506040850135613c1981613586565b9396929550929360600135925050565b600181811c90821680613c3d57607f821691505b6020821081036135ad57634e487b7160e01b600052602260045260246000fd5b8183823760009101908152919050565b6000808335601e19843603018112613c8457600080fd5b8301803591506001600160401b03821115613c9e57600080fd5b60200191503681900382131561346657600080fd5b6020808252602d908201527f426173654f4654576974684665653a20616d6f756e74206973206c657373207460408201526c1a185b881b5a5b905b5bdd5b9d609a1b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff84168152604060208201526000611c8d604083018486613d00565b60208082526025908201527f4665653a20666565206270206d757374206265203c3d2042505f44454e4f4d496040820152642720aa27a960d91b606082015260800190565b600060208284031215613d9e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610bb257610bb2613da5565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b601f821115612e4057600081815260208120601f850160051c81016020861015613e1b5750805b601f850160051c820191505b81811015610d5357828155600101613e27565b81516001600160401b03811115613e5357613e536137ce565b613e6781613e618454613c29565b84613df4565b602080601f831160018114613e9c5760008415613e845750858301515b600019600386901b1c1916600185901b178555610d53565b600085815260208120601f198616915b82811015613ecb57888601518255948401946001909101908401613eac565b5085821015613ee95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600061ffff808816835280871660208401525084604083015260806060830152613365608083018486613d00565b61ffff86168152608060208201526000613f45608083018688613d00565b6001600160401b0394909416604083015250606001529392505050565b61ffff8916815260c060208201526000613f8060c08301898b613d00565b6001600160401b038816604084015286606084015285608084015282810360a0840152613fae818587613d00565b9b9a5050505050505050505050565b6001600160401b03831115613fd457613fd46137ce565b613fe883613fe28354613c29565b83613df4565b6000601f84116001811461401c57600085156140045750838201355b600019600387901b1c1916600186901b178355610c3a565b600083815260209020601f19861690835b8281101561404d578685013582556020948501946001909201910161402d565b508682101561406a5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8082028115828204841417610bb257610bb2613da5565b634e487b7160e01b600052601260045260246000fd5b6000826140b8576140b8614093565b500490565b6000602082840312156140cf57600080fd5b81516001600160401b038111156140e557600080fd5b8201601f810184136140f657600080fd5b805161410461389382613814565b81815285602083850101111561411957600080fd5b6124d28260208301602086016138db565b61ffff8516815260806020820152600061414760808301866138ff565b6001600160401b0385166040840152828103606084015261336581856138ff565b61ffff861681526001600160a01b038516602082015260a060408201819052600090614196908301866138ff565b841515606084015282810360808401526141b081856138ff565b98975050505050505050565b600080604083850312156141cf57600080fd5b505080516020909101519092909150565b80820180821115610bb257610bb2613da5565b600082516142058184602087016138db565b9190910192915050565b61ffff8616815260a06020820152600061422c60a08301876138ff565b6001600160401b0386166040840152828103606084015261424d81866138ff565b905082810360808401526141b081856138ff565b60008261427057614270614093565b500690565b61ffff8716815260c06020820152600061429260c08301886138ff565b82810360408401526142a481886138ff565b6001600160a01b0387811660608601528616608085015283810360a085015290506142cf81856138ff565b9998505050505050505050565b60ff60f81b8760f81b16815285600182015260006001600160401b0360c01b808760c01b166021840152856029840152808560c01b16604984015250825161432b8160518501602087016138db565b91909101605101979650505050505050565b600061010061ffff8b16835280602084015261435b8184018b6138ff565b6001600160401b038a166040850152606084018990526001600160a01b038816608085015260a0840187905283810360c0850152905061439b81866138ff565b9150508260e08301529998505050505050505050565b6060815260006143c460608301866138ff565b6001600160401b039490941660208301525060400152919050565b6000602082840312156143f157600080fd5b8151610e768161362e56fea26469706673582212204495807a73f54df216e7031f0d93c92bdc992182a5b4b976b789686dedbed27264736f6c63430008140033

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

000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9000000000000000000000000000000000000000000000000000000000000000800000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675

-----Decoded View---------------
Arg [0] : _token (address): 0xa6C0c097741D55ECd9a3A7DeF3A8253fD022ceB9
Arg [1] : _sharedDecimals (uint8): 8
Arg [2] : _lzEndpoint (address): 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a6c0c097741d55ecd9a3a7def3a8253fd022ceb9
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [2] : 00000000000000000000000066a71dcef29a0ffbdbe3c6a460a3b5bc225cd675


Deployed Bytecode Sourcemap

88764:3158:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31536:799;;;;;;;;;;-1:-1:-1;31536:799:0;;;;;:::i;:::-;;:::i;:::-;;66249:218;;;;;;;;;;-1:-1:-1;66249:218:0;;;;;:::i;:::-;;:::i;:::-;;;2029:14:1;;2022:22;2004:41;;1992:2;1977:18;66249:218:0;;;;;;;;34945:123;;;;;;;;;;-1:-1:-1;34945:123:0;;;;;:::i;:::-;;:::i;36814:142::-;;;;;;;;;;-1:-1:-1;36814:142:0;;;;;:::i;:::-;;:::i;35076:129::-;;;;;;;;;;-1:-1:-1;35076:129:0;;;;;:::i;:::-;;:::i;64620:648::-;;;;;;:::i;:::-;;:::i;66475:344::-;;;;;;;;;;-1:-1:-1;66475:344:0;;;;;:::i;:::-;;:::i;:::-;;;;4638:25:1;;;4694:2;4679:18;;4672:34;;;;4611:18;66475:344:0;4464:248:1;37054:250:0;;;;;;;;;;-1:-1:-1;37054:250:0;;;;;:::i;:::-;;:::i;31078:53::-;;;;;;;;;;-1:-1:-1;31078:53:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;5349:25:1;;;5337:2;5322:18;31078:53:0;5203:177:1;35213:178:0;;;;;;;;;;-1:-1:-1;35213:178:0;;;;;:::i;:::-;;:::i;49148:37::-;;;;;;;;;;;;49184:1;49148:37;;65276:776;;;;;;:::i;:::-;;:::i;62270:217::-;;;;;;;;;;-1:-1:-1;62270:217:0;;;;;:::i;:::-;;:::i;49214:33::-;;;;;;;;;;;;49246:1;49214:33;;;;;6976:4:1;6964:17;;;6946:36;;6934:2;6919:18;49214:33:0;6804:184:1;61709:235:0;;;;;;;;;;-1:-1:-1;61709:235:0;;;;;:::i;:::-;;:::i;43291:85::-;;;;;;;;;;-1:-1:-1;43291:85:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44571:346;;;;;;;;;;-1:-1:-1;44571:346:0;;;;;:::i;:::-;;:::i;2658:103::-;;;;;;;;;;;;;:::i;30948:51::-;;;;;;;;;;-1:-1:-1;30948:51:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;61952:310::-;;;;;;;;;;-1:-1:-1;61952:310:0;;;;;:::i;:::-;;:::i;49305:37::-;;;;;;;;;;;;;;;31006:65;;;;;;;;;;-1:-1:-1;31006:65:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;2017:87;;;;;;;;;;-1:-1:-1;2063:7:0;2090:6;-1:-1:-1;;;;;2090:6:0;2017:87;;;-1:-1:-1;;;;;10165:32:1;;;10147:51;;10135:2;10120:18;2017:87:0;10001:203:1;89837:140:0;;;;;;;;;;;;;:::i;31138:23::-;;;;;;;;;;-1:-1:-1;31138:23:0;;;;-1:-1:-1;;;;;31138:23:0;;;89052:26;;;;;;;;;;;;;;;;49351:83;;;;;;;;;;-1:-1:-1;49351:83:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36042:330;;;;;;;;;;-1:-1:-1;36042:330:0;;;;;:::i;:::-;;:::i;66827:450::-;;;;;;;;;;-1:-1:-1;66827:450:0;;;;;:::i;:::-;;:::i;35753:281::-;;;;;;;;;;-1:-1:-1;35753:281:0;;;;;:::i;:::-;;:::i;61221:43::-;;;;;;;;;;;;61259:5;61221:43;;30895:46;;;;;;;;;;;;;;;61364:23;;;;;;;;;;-1:-1:-1;61364:23:0;;;;;;;-1:-1:-1;;;;;61364:23:0;;;36380:136;;;;;;;;;;-1:-1:-1;36380:136:0;;;;;:::i;:::-;;:::i;61273:51::-;;;;;;;;;;-1:-1:-1;61273:51:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;11774:6:1;11762:19;;;11744:38;;11825:14;;11818:22;11813:2;11798:18;;11791:50;11717:18;61273:51:0;11578:269:1;34733:204:0;;;;;;;;;;-1:-1:-1;34733:204:0;;;;;:::i;:::-;;:::i;45103:767::-;;;;;;:::i;:::-;;:::i;61331:26::-;;;;;;;;;;-1:-1:-1;61331:26:0;;;;;;;;;;;12653:6:1;12641:19;;;12623:38;;12611:2;12596:18;61331:26:0;12479:188:1;36524:228:0;;;;;;;;;;-1:-1:-1;36524:228:0;;;;;:::i;:::-;;:::i;49254:42::-;;;;;;;;;;;;49295:1;49254:42;;50555:643;;;;;;;;;;-1:-1:-1;50555:643:0;;;;;:::i;:::-;;:::i;35538:207::-;;;;;;;;;;-1:-1:-1;35538:207:0;;;;;:::i;:::-;;:::i;62495:413::-;;;;;;;;;;-1:-1:-1;62495:413:0;;;;;:::i;:::-;;:::i;2916:201::-;;;;;;;;;;-1:-1:-1;2916:201:0;;;;;:::i;:::-;;:::i;34460:211::-;;;;;;;;;;-1:-1:-1;34460:211:0;;;;;:::i;:::-;;:::i;89985:109::-;;;;;;;;;;-1:-1:-1;90075:10:0;89985:109;;31536:799;736:10;31776;-1:-1:-1;;;;;31752:35:0;;31744:78;;;;-1:-1:-1;;;31744:78:0;;14878:2:1;31744:78:0;;;14860:21:1;14917:2;14897:18;;;14890:30;14956:32;14936:18;;;14929:60;15006:18;;31744:78:0;;;;;;;;;31864:32;;;31835:26;31864:32;;;:19;:32;;;;;31835:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32084:13;:20;32062:11;;:18;;:42;:70;;;;;32131:1;32108:13;:20;:24;32062:70;:124;;;;-1:-1:-1;32162:24:0;;;;;;32136:22;;;;32146:11;;;;32136:22;:::i;:::-;;;;;;;;:50;32062:124;32040:212;;;;-1:-1:-1;;;32040:212:0;;15898:2:1;32040:212:0;;;15880:21:1;15937:2;15917:18;;;15910:30;15976:34;15956:18;;;15949:62;-1:-1:-1;;;16027:18:1;;;16020:36;16073:19;;32040:212:0;15696:402:1;32040:212:0;32265:62;32284:11;32297;;32265:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;32265:62:0;;;;;;;;;;;;;;;;;;;;;;32310:6;;-1:-1:-1;32265:62:0;-1:-1:-1;32318:8:0;;;;;;32265:62;;32318:8;;;;32265:62;;;;;;;;;-1:-1:-1;32265:18:0;;-1:-1:-1;;;32265:62:0:i;:::-;31667:668;31536:799;;;;;;:::o;66249:218::-;66351:4;-1:-1:-1;;;;;;66375:44:0;;-1:-1:-1;;;66375:44:0;;:84;;-1:-1:-1;;;;;;;;;;64196:40:0;;;66423:36;66368:91;66249:218;-1:-1:-1;;66249:218:0:o;34945:123::-;1903:13;:11;:13::i;:::-;35025:35:::1;::::0;-1:-1:-1;;;35025:35:0;;12653:6:1;12641:19;;35025:35:0::1;::::0;::::1;12623:38:1::0;35025:10:0::1;-1:-1:-1::0;;;;;35025:25:0::1;::::0;::::1;::::0;12596:18:1;;35025:35:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;34945:123:::0;:::o;36814:142::-;1903:13;:11;:13::i;:::-;36905:35:::1;::::0;;::::1;;::::0;;;:22:::1;:35;::::0;;;;:43;36814:142::o;35076:129::-;1903:13;:11;:13::i;:::-;35159:38:::1;::::0;-1:-1:-1;;;35159:38:0;;12653:6:1;12641:19;;35159:38:0::1;::::0;::::1;12623::1::0;35159:10:0::1;-1:-1:-1::0;;;;;35159:28:0::1;::::0;::::1;::::0;12596:18:1;;35159:38:0::1;12479:188:1::0;64620:648:0;64877:39;64888:5;64895:11;64908:7;64877:10;:39::i;:::-;-1:-1:-1;64863:53:0;-1:-1:-1;64937:233:0;64957:5;64977:11;65003:10;64863:53;65050:25;;;;:11;:25;:::i;:::-;65090:29;;;;;;;;:::i;:::-;65134:25;;;;:11;:25;:::i;:::-;64937:233;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64937:5:0;;-1:-1:-1;;;64937:233:0:i;:::-;64927:243;;65200:10;65189:7;:21;;65181:79;;;;-1:-1:-1;;;65181:79:0;;;;;;;:::i;:::-;64620:648;;;;;;:::o;66475:344::-;66689:14;66705:11;66736:75;66753:11;66766:10;66778:7;66787;66796:14;;66736:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66736:16:0;;-1:-1:-1;;;66736:75:0:i;:::-;66729:82;;;;66475:344;;;;;;;;;:::o;37054:250::-;37196:32;;;37150:4;37196:32;;;:19;:32;;;;;37167:61;;37150:4;;37196:32;37167:61;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37284:11;;37274:22;;;;;;;:::i;:::-;;;;;;;;37256:13;37246:24;;;;;;:50;37239:57;;;37054:250;;;;;;:::o;35213:178::-;1903:13;:11;:13::i;:::-;35328:55:::1;::::0;-1:-1:-1;;;35328:55:0;;-1:-1:-1;;;;;35328:10:0::1;:29;::::0;::::1;::::0;:55:::1;::::0;35358:11;;35371;;;;35328:55:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;65276:776:::0;65602:39;65613:5;65620:11;65633:7;65602:10;:39::i;:::-;65588:53;;;;;65662:292;65689:5;65709:11;65735:10;65760:7;65782:8;;65662:292;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65805:14:0;;-1:-1:-1;65834:25:0;;-1:-1:-1;;65834:25:0;;;:11;:25;:::i;:::-;65874:29;;;;;;;;:::i;:::-;65918:25;;;;:11;:25;:::i;:::-;65662:292;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65662:12:0;;-1:-1:-1;;;65662:292:0:i;:::-;65652:302;;65984:10;65973:7;:21;;65965:79;;;;-1:-1:-1;;;65965:79:0;;;;;;;:::i;:::-;65276:776;;;;;;;;;:::o;62270:217::-;1903:13;:11;:13::i;:::-;-1:-1:-1;;;;;62354:25:0;::::1;62346:64;;;::::0;-1:-1:-1;;;62346:64:0;;18107:2:1;62346:64:0::1;::::0;::::1;18089:21:1::0;18146:2;18126:18;;;18119:30;18185:28;18165:18;;;18158:56;18231:18;;62346:64:0::1;17905:350:1::0;62346:64:0::1;62421:8;:20:::0;;-1:-1:-1;;;;;;62421:20:0::1;::::0;-1:-1:-1;;;;;62421:20:0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;62457:22:::1;::::0;10147:51:1;;;62457:22:0::1;::::0;10135:2:1;10120:18;62457:22:0::1;;;;;;;;62270:217:::0;:::o;61709:235::-;1903:13;:11;:13::i;:::-;61259:5:::1;61793:6;:24;;;;61785:74;;;;-1:-1:-1::0;;;61785:74:0::1;;;;;;;:::i;:::-;61870:12;:21:::0;;-1:-1:-1;;61870:21:0::1;;::::0;::::1;::::0;;::::1;::::0;;;61907:29:::1;::::0;12623:38:1;;;61907:29:0::1;::::0;12611:2:1;12596:18;61907:29:0::1;12479:188:1::0;44571:346:0;736:10;44785:4;44761:29;44753:80;;;;-1:-1:-1;;;44753:80:0;;18868:2:1;44753:80:0;;;18850:21:1;18907:2;18887:18;;;18880:30;18946:34;18926:18;;;18919:62;-1:-1:-1;;;18997:18:1;;;18990:36;19043:19;;44753:80:0;18666:402:1;44753:80:0;44844:65;44866:11;44879;;44844:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;44844:65:0;;;;;;;;;;;;;;;;;;;;;;44892:6;;-1:-1:-1;44844:65:0;-1:-1:-1;44900:8:0;;;;;;44844:65;;44900:8;;;;44844:65;;;;;;;;;-1:-1:-1;44844:21:0;;-1:-1:-1;;;44844:65:0:i;2658:103::-;1903:13;:11;:13::i;:::-;2723:30:::1;2750:1;2723:18;:30::i;:::-;2658:103::o:0;30948:51::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;61952:310::-;1903:13;:11;:13::i;:::-;61259:5:::1;62064:6;:24;;;;62056:74;;;;-1:-1:-1::0;;;62056:74:0::1;;;;;;;:::i;:::-;62172:27;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;62141:28;;::::1;-1:-1:-1::0;62141:28:0;;;:15:::1;:28:::0;;;;;:58;;;;;;::::1;;::::0;::::1;-1:-1:-1::0;;62141:58:0;;;;::::1;::::0;;;;::::1;::::0;;;62215:39;;19290:34:1;;;19340:18;;;19333:50;;;;19399:18;;;19392:43;62215:39:0::1;::::0;19253:2:1;19238:18;62215:39:0::1;;;;;;;;61952:310:::0;;;:::o;89837:140::-;89904:4;89955:14;;89928:10;-1:-1:-1;;;;;89928:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:41;;;;:::i;:::-;89921:48;;89837:140;:::o;36042:330::-;36166:35;;;36146:17;36166:35;;;:19;:35;;;;;36146:55;;36121:12;;36146:17;36166:35;36146:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36220:4;:11;36235:1;36220:16;36212:58;;;;-1:-1:-1;;;36212:58:0;;20102:2:1;36212:58:0;;;20084:21:1;20141:2;20121:18;;;20114:30;20180:31;20160:18;;;20153:59;20229:18;;36212:58:0;19900:353:1;36212:58:0;36288:31;36299:1;36316:2;36302:4;:11;:16;;;;:::i;:::-;36288:4;;:31;:10;:31::i;66827:450::-;67114:14;67130:11;67161:108;67185:11;67198:10;67210:7;67219:8;;67161:108;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67161:108:0;;;;;;;;;;;;;;;;;;;;;;67229:14;;-1:-1:-1;67245:7:0;;-1:-1:-1;67161:108:0;67254:14;;;;;;67161:108;;67254:14;;;;67161:108;;;;;;;;;-1:-1:-1;67161:23:0;;-1:-1:-1;;;67161:108:0:i;:::-;67154:115;;;;66827:450;;;;;;;;;;;;:::o;35753:281::-;1903:13;:11;:13::i;:::-;35925:14:::1;;35949:4;35908:47;;;;;;;;;;:::i;:::-;;::::0;;-1:-1:-1;;35908:47:0;;::::1;::::0;;;;;;35870:35:::1;::::0;::::1;;::::0;;;:19:::1;35908:47;35870:35:::0;;;:85:::1;::::0;:35;:85:::1;:::i;:::-;;35971:55;35995:14;36011;;35971:55;;;;;;;;:::i;36380:136::-:0;1903:13;:11;:13::i;:::-;36450:8:::1;:20:::0;;-1:-1:-1;;;;;;36450:20:0::1;-1:-1:-1::0;;;;;36450:20:0;::::1;::::0;;::::1;::::0;;;36486:22:::1;::::0;10147:51:1;;;36486:22:0::1;::::0;10135:2:1;10120:18;36486:22:0::1;10001:203:1::0;34733:204:0;1903:13;:11;:13::i;:::-;34867:62:::1;::::0;-1:-1:-1;;;34867:62:0;;-1:-1:-1;;;;;34867:10:0::1;:20;::::0;::::1;::::0;:62:::1;::::0;34888:8;;34898;;34908:11;;34921:7;;;;34867:62:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;45103:767:::0;45314:27;;;45292:19;45314:27;;;:14;:27;;;;;;:40;;;;45342:11;;;;45314:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;45314:48:0;;;;;;;;;;;;-1:-1:-1;45314:48:0;45373:73;;;;-1:-1:-1;;;45373:73:0;;23526:2:1;45373:73:0;;;23508:21:1;23565:2;23545:18;;;23538:30;23604:34;23584:18;;;23577:62;-1:-1:-1;;;23655:18:1;;;23648:33;23698:19;;45373:73:0;23324:399:1;45373:73:0;45488:11;45475:8;;45465:19;;;;;;;:::i;:::-;;;;;;;;:34;45457:80;;;;-1:-1:-1;;;45457:80:0;;23930:2:1;45457:80:0;;;23912:21:1;23969:2;23949:18;;;23942:30;24008:34;23988:18;;;23981:62;-1:-1:-1;;;24059:18:1;;;24052:31;24100:19;;45457:80:0;23728:397:1;45457:80:0;45585:27;;;45644:1;45585:27;;;:14;:27;;;;;;:40;;;;45613:11;;;;45585:40;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;45585:48:0;;;;;;;;;;;;:61;;;;45715:65;;;;;;;;;;;;;;;;;;;45737:11;;45750;;45715:65;;;;;;45750:11;45715:65;;45750:11;45715:65;;;;;;;;;-1:-1:-1;;45715:65:0;;;;;;;;;;;;;;;;;;;;;;45763:6;;-1:-1:-1;45715:65:0;-1:-1:-1;45771:8:0;;;;;;45715:65;;45771:8;;;;45715:65;;;;;;;;;-1:-1:-1;45715:21:0;;-1:-1:-1;;;45715:65:0:i;:::-;45796:66;45816:11;45829;;45842:6;45850:11;45796:66;;;;;;;;;;:::i;:::-;;;;;;;;45236:634;45103:767;;;;;;:::o;36524:228::-;1903:13;:11;:13::i;:::-;36630:28:::1;::::0;;::::1;;::::0;;;:15:::1;:28;::::0;;;;;;;:41;;::::1;::::0;;;;;;;;;;:51;;;36697:47;;24851:34:1;;;24901:18;;24894:43;;;;24953:18;;;24946:34;;;36697:47:0::1;::::0;24814:2:1;24799:18;36697:47:0::1;24628:358:1::0;50555:643:0;736:10;50867:4;50843:29;50835:73;;;;-1:-1:-1;;;50835:73:0;;25193:2:1;50835:73:0;;;25175:21:1;25232:2;25212:18;;;25205:30;25271:33;25251:18;;;25244:61;25322:18;;50835:73:0;24991:355:1;50835:73:0;50948:42;50970:4;50977:3;50982:7;50948:13;:42::i;:::-;50938:52;;51036:3;-1:-1:-1;;;;;51006:43:0;51023:11;51006:43;;;51041:7;51006:43;;;;5349:25:1;;5337:2;5322:18;;5203:177;51006:43:0;;;;;;;;51079:111;;-1:-1:-1;;;51079:111:0;;-1:-1:-1;;;;;51079:33:0;;;;;51118:11;;51079:111;;51131:11;;51144;;;;51157:6;;51165:5;;51172:7;;51181:8;;;;51079:111;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50555:643;;;;;;;;;;:::o;35538:207::-;1903:13;:11;:13::i;:::-;35639:35:::1;::::0;::::1;;::::0;;;:19:::1;:35;::::0;;;;:43:::1;35677:5:::0;;35639:35;:43:::1;:::i;:::-;;35698:39;35715:14;35731:5;;35698:39;;;;;;;;:::i;62495:413::-:0;62626:28;;;;62579:8;62626:28;;;:15;:28;;;;;;;;62600:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62579:8;;62600:54;62665:236;;62717:12;;61259:5;;62707:22;;;;:7;:22;:::i;:::-;62706:41;;;;:::i;:::-;62700:47;;62665:236;;;62769:12;;;;:16;62765:136;;62819:12;;61259:5;;62809:22;;62819:12;;62809:7;:22;:::i;62765:136::-;62888:1;62882:7;;62765:136;62589:319;62495:413;;;;:::o;2916:201::-;1903:13;:11;:13::i;:::-;-1:-1:-1;;;;;3005:22:0;::::1;2997:73;;;::::0;-1:-1:-1;;;2997:73:0;;27948:2:1;2997:73:0::1;::::0;::::1;27930:21:1::0;27987:2;27967:18;;;27960:30;28026:34;28006:18;;;27999:62;-1:-1:-1;;;28077:18:1;;;28070:36;28123:19;;2997:73:0::1;27746:402:1::0;2997:73:0::1;3081:28;3100:8;3081:18;:28::i;:::-;2916:201:::0;:::o;34460:211::-;34595:68;;-1:-1:-1;;;34595:68:0;;28390:6:1;28423:15;;;34595:68:0;;;28405:34:1;28475:15;;28455:18;;;28448:43;34644:4:0;28507:18:1;;;28500:60;28576:18;;;28569:34;;;34563:12:0;;34595:10;-1:-1:-1;;;;;34595:20:0;;;;28352:19:1;;34595:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;34595:68:0;;;;;;;;;;;;:::i;:::-;34588:75;;34460:211;;;;;;;:::o;43660:520::-;43810:12;43824:19;43847:203;43895:9;43919:3;43960:34;;;43996:11;44009;44022:6;44030:8;43937:102;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;43937:102:0;;;;;;;;;;;;;;-1:-1:-1;;;;;43937:102:0;-1:-1:-1;;;;;;43937:102:0;;;;;;;;;;43855:4;;43847:203;;:33;:203::i;:::-;43809:241;;;;44066:7;44061:112;;44090:71;44110:11;44123;44136:6;44144:8;44154:6;44090:19;:71::i;2182:132::-;2063:7;2090:6;-1:-1:-1;;;;;2090:6:0;736:10;2246:23;2238:68;;;;-1:-1:-1;;;2238:68:0;;30028:2:1;2238:68:0;;;30010:21:1;;;30047:18;;;30040:30;30106:34;30086:18;;;30079:62;30158:18;;2238:68:0;29826:356:1;62916:294:0;63011:11;63024:8;63051:33;63063:11;63076:7;63051:11;:33::i;:::-;63045:39;-1:-1:-1;63104:13:0;63045:39;63104:7;:13;:::i;:::-;63095:22;-1:-1:-1;63132:7:0;;63128:75;;63177:8;;63156:35;;63170:5;;63177:8;;;-1:-1:-1;;;;;63177:8:0;63187:3;63156:13;:35::i;:::-;;63128:75;62916:294;;;;;;:::o;53035:840::-;53304:11;53328:66;53343:11;53304;53365:14;53304:11;53328:14;:66::i;:::-;53420:20;53432:7;53420:11;:20::i;:::-;-1:-1:-1;53407:33:0;-1:-1:-1;53460:50:0;53471:5;53478:11;53491:10;53407:33;53460:10;:50::i;:::-;53451:59;;53578:1;53569:6;:10;53561:48;;;;-1:-1:-1;;;53561:48:0;;30389:2:1;53561:48:0;;;30371:21:1;30428:2;30408:18;;;30401:30;-1:-1:-1;;;30447:18:1;;;30440:55;30512:18;;53561:48:0;30187:349:1;53561:48:0;53622:22;53647:46;53666:10;53678:14;53685:6;53678;:14::i;:::-;57995:48;;;49246:1;57995:48;;;35806:49:1;35871:11;;;35864:27;;;;35947:3;35925:16;;;;-1:-1:-1;;;;;;35921:51:1;35907:12;;;35900:73;57995:48:0;;;;;;;;;35989:12:1;;;;57995:48:0;;;57866:185;53647:46;53622:71;;53704:94;53712:11;53725:9;53736:14;53752:18;53772:14;53788:9;53704:7;:94::i;:::-;53848:10;53841:5;-1:-1:-1;;;;;53816:51:0;53828:11;53816:51;;;53860:6;53816:51;;;;5349:25:1;;5337:2;5322:18;;5203:177;53816:51:0;;;;;;;;53317:558;53035:840;;;;;;;;;:::o;51392:471::-;51598:14;51614:11;51682:20;51705:47;51724:10;51736:15;51743:7;51736:6;:15::i;51705:47::-;51770:85;;-1:-1:-1;;;51770:85:0;;51682:70;;-1:-1:-1;;;;;;51770:10:0;:23;;;;:85;;51794:11;;51815:4;;51682:70;;51831:7;;51840:14;;51770:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51763:92;;;;;51392:471;;;;;;;;:::o;54305:995::-;54645:11;54669:77;54684:11;49295:1;54715:14;-1:-1:-1;;;;;54669:77:0;;:14;:77::i;:::-;54772:20;54784:7;54772:11;:20::i;:::-;-1:-1:-1;54759:33:0;-1:-1:-1;54812:50:0;54823:5;54830:11;54843:10;54759:33;54812:10;:50::i;:::-;54803:59;;54890:1;54881:6;:10;54873:48;;;;-1:-1:-1;;;54873:48:0;;30389:2:1;54873:48:0;;;30371:21:1;30428:2;30408:18;;;30401:30;-1:-1:-1;;;30447:18:1;;;30440:55;30512:18;;54873:48:0;30187:349:1;54873:48:0;55002:22;55027:91;55053:10;55065;55077:14;55084:6;55077;:14::i;:::-;55093:8;55103:14;55027:25;:91::i;:::-;55002:116;;55129:94;55137:11;55150:9;55161:14;55177:18;55197:14;55213:9;55129:7;:94::i;:::-;55273:10;55266:5;-1:-1:-1;;;;;55241:51:0;55253:11;55241:51;;;55285:6;55241:51;;;;5349:25:1;;5337:2;5322:18;;5203:177;55241:51:0;;;;;;;;54658:642;54305:995;;;;;;;;;;;:::o;52469:558::-;52664:16;52683:19;:8;52664:16;52683;:19::i;:::-;52664:38;-1:-1:-1;52719:21:0;;;52715:305;;52757:52;52766:11;52779;52792:6;52800:8;52757;:52::i;:::-;52715:305;;;-1:-1:-1;;52831:30:0;;;;52827:193;;52878:59;52894:11;52907;52920:6;52928:8;52878:15;:59::i;52827:193::-;52970:38;;-1:-1:-1;;;52970:38:0;;31638:2:1;52970:38:0;;;31620:21:1;31677:2;31657:18;;;31650:30;31716;31696:18;;;31689:58;31764:18;;52970:38:0;31436:352:1;3277:191:0;3351:16;3370:6;;-1:-1:-1;;;;;3387:17:0;;;-1:-1:-1;;;;;;3387:17:0;;;;;;3420:40;;3370:6;;;;;;;3420:40;;3351:16;3420:40;3340:128;3277:191;:::o;20579:2799::-;20665:12;20714:7;20698:12;20714:7;20708:2;20698:12;:::i;:::-;:23;;20690:50;;;;-1:-1:-1;;;20690:50:0;;32125:2:1;20690:50:0;;;32107:21:1;32164:2;32144:18;;;32137:30;-1:-1:-1;;;32183:18:1;;;32176:44;32237:18;;20690:50:0;31923:338:1;20690:50:0;20776:16;20785:7;20776:6;:16;:::i;:::-;20759:6;:13;:33;;20751:63;;;;-1:-1:-1;;;20751:63:0;;32468:2:1;20751:63:0;;;32450:21:1;32507:2;32487:18;;;32480:30;-1:-1:-1;;;32526:18:1;;;32519:47;32583:18;;20751:63:0;32266:341:1;20751:63:0;20827:22;20893:15;;20922:2005;;;;23071:4;23065:11;23052:24;;23260:1;23249:9;23242:20;23310:4;23299:9;23295:20;23289:4;23282:34;20886:2445;;20922:2005;21107:4;21101:11;21088:24;;21776:2;21767:7;21763:16;22164:9;22157:17;22151:4;22147:28;22135:9;22124;22120:25;22116:60;22213:7;22209:2;22205:16;22470:6;22456:9;22449:17;22443:4;22439:28;22427:9;22419:6;22415:22;22411:57;22407:70;22241:434;22504:3;22500:2;22497:11;22241:434;;;22646:9;;22635:21;;22546:4;22538:13;;;;22579;22241:434;;;-1:-1:-1;;22695:26:0;;;22907:2;22890:11;-1:-1:-1;;22886:25:0;22880:4;22873:39;-1:-1:-1;20886:2445:0;-1:-1:-1;23361:9:0;20579:2799;-1:-1:-1;;;;20579:2799:0:o;51871:590::-;52148:14;52164:11;52235:20;52258:92;52284:10;52296;52308:15;52315:7;52308:6;:15::i;52258:92::-;52368:85;;-1:-1:-1;;;52368:85:0;;52235:115;;-1:-1:-1;;;;;;52368:10:0;:23;;;;:85;;52392:11;;52413:4;;52235:115;;52429:7;;52438:14;;52368:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52361:92;;;;;51871:590;;;;;;;;;;:::o;91409:399::-;91540:25;;-1:-1:-1;;;91540:25:0;;-1:-1:-1;;;;;10165:32:1;;;91540:25:0;;;10147:51:1;91509:4:0;;;;91540:10;:20;;;;10120:18:1;;91540:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91526:39;-1:-1:-1;91597:4:0;-1:-1:-1;;;;;91580:22:0;;;91576:173;;91619:37;-1:-1:-1;;;;;91619:10:0;:23;91643:3;91648:7;91619:23;:37::i;:::-;91576:173;;;91689:48;-1:-1:-1;;;;;91689:10:0;:27;91717:5;91724:3;91729:7;91689:27;:48::i;:::-;91766:25;;-1:-1:-1;;;91766:25:0;;-1:-1:-1;;;;;10165:32:1;;;91766:25:0;;;10147:51:1;91794:6:0;;91766:10;:20;;;;;;10120:18:1;;91766:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:34;;;;:::i;:::-;91759:41;91409:399;-1:-1:-1;;;;;91409:399:0:o;38368:1266::-;38484:4;38490:12;38552;38575:13;38599:24;38636:8;38626:19;;-1:-1:-1;;;;;38626:19:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38626:19:0;;38599:46;;39155:1;39125;39087:9;39081:16;39048:4;39037:9;39033:20;38998:1;38959:7;38929:4;38906:275;38894:287;;39250:16;39239:27;;39295:8;39286:7;39283:21;39280:78;;;39335:8;39324:19;;39280:78;39445:7;39432:11;39425:28;39567:7;39564:1;39557:4;39544:11;39540:22;39525:50;39604:8;;;;-1:-1:-1;38368:1266:0;-1:-1:-1;;;;;;38368:1266:0:o;44188:375::-;44464:8;44454:19;;;;;;44403:14;:27;44418:11;44403:27;;;;;;;;;;;;;;;44431:11;44403:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44403:48:0;;;;;;;;;:70;;;;44489:66;;;;44503:11;;44516;;44444:6;;44537:8;;44547:7;;44489:66;:::i;:::-;;;;;;;;44188:375;;;;;:::o;33246:420::-;33382:21;33406:28;33419:14;33406:12;:28::i;:::-;33464;;;;33445:16;33464:28;;;:15;:28;;;;;;;;:35;;;;;;;;;;33382:52;;-1:-1:-1;33518:15:0;33510:54;;;;-1:-1:-1;;;33510:54:0;;33827:2:1;33510:54:0;;;33809:21:1;33866:2;33846:18;;;33839:30;33905:28;33885:18;;;33878:56;33951:18;;33510:54:0;33625:350:1;33510:54:0;33603:23;33617:9;33603:11;:23;:::i;:::-;33583:16;:43;;33575:83;;;;-1:-1:-1;;;33575:83:0;;34182:2:1;33575:83:0;;;34164:21:1;34221:2;34201:18;;;34194:30;34260:29;34240:18;;;34233:57;34307:18;;33575:83:0;33980:351:1;57676:182:0;57742:16;;57789:22;91902:9;57789:7;:22;:::i;:::-;57782:29;-1:-1:-1;57836:14:0;57782:29;57836:7;:14;:::i;:::-;57822:28;;57676:182;;;:::o;90288:732::-;90389:4;-1:-1:-1;;;;;90414:21:0;;736:10;90414:21;90406:75;;;;-1:-1:-1;;;90406:75:0;;34655:2:1;90406:75:0;;;34637:21:1;34694:2;34674:18;;;34667:30;34733:34;34713:18;;;34706:62;-1:-1:-1;;;34784:18:1;;;34777:39;34833:19;;90406:75:0;34453:405:1;90406:75:0;90504:44;90518:5;90533:4;90540:7;90504:13;:44::i;:::-;90494:54;;90671:11;90684:9;90697:20;90709:7;90697:11;:20::i;:::-;90670:47;;-1:-1:-1;90670:47:0;-1:-1:-1;90732:8:0;;90728:50;;90742:36;-1:-1:-1;;;;;90742:10:0;:23;90766:5;90773:4;90742:23;:36::i;:::-;90849:6;90831:14;;:24;;;;;;;:::i;:::-;;;;-1:-1:-1;90866:8:0;;-1:-1:-1;90877:24:0;-1:-1:-1;;;;;90877:6:0;:24::i;:::-;90866:35;;90927:14;;90920:3;:21;;90912:74;;;;-1:-1:-1;;;90912:74:0;;35065:2:1;90912:74:0;;;35047:21:1;35104:2;35084:18;;;35077:30;35143:34;35123:18;;;35116:62;-1:-1:-1;;;35194:18:1;;;35187:38;35242:19;;90912:74:0;34863:404:1;90912:74:0;-1:-1:-1;91006:6:0;;90288:732;-1:-1:-1;;;;;;90288:732:0:o;57301:238::-;57362:6;;57397:22;91902:9;57397:7;:22;:::i;:::-;57381:38;-1:-1:-1;;;;;;57438:28:0;;;57430:67;;;;-1:-1:-1;;;57430:67:0;;35474:2:1;57430:67:0;;;35456:21:1;35513:2;35493:18;;;35486:30;35552:28;35532:18;;;35525:56;35598:18;;57430:67:0;35272:350:1;32624:614:0;32908:32;;;32879:26;32908:32;;;:19;:32;;;;;32879:61;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32959:13;:20;32983:1;32959:25;32951:86;;;;-1:-1:-1;;;32951:86:0;;36214:2:1;32951:86:0;;;36196:21:1;36253:2;36233:18;;;36226:30;36292:34;36272:18;;;36265:62;-1:-1:-1;;;36343:18:1;;;36336:46;36399:19;;32951:86:0;36012:412:1;32951:86:0;33048:47;33066:11;33079:8;:15;33048:17;:47::i;:::-;33106:124;;-1:-1:-1;;;33106:124:0;;-1:-1:-1;;;;;33106:10:0;:15;;;;33129:10;;33106:124;;33141:11;;33154:13;;33169:8;;33179:14;;33195:18;;33215:14;;33106:124;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32868:370;32624:614;;;;;;:::o;58410:366::-;58627:12;49295:1;58694:10;58706:9;-1:-1:-1;;;;;59460:23:0;;58743:14;58759:8;58659:109;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;58652:116;;58410:366;;;;;;;:::o;23754:307::-;23828:5;23871:10;:6;23880:1;23871:10;:::i;:::-;23854:6;:13;:27;;23846:59;;;;-1:-1:-1;;;23846:59:0;;38205:2:1;23846:59:0;;;38187:21:1;38244:2;38224:18;;;38217:30;-1:-1:-1;;;38263:18:1;;;38256:49;38322:18;;23846:59:0;38003:343:1;23846:59:0;-1:-1:-1;23985:29:0;24001:3;23985:29;23979:36;;23754:307::o;53883:414::-;53995:10;54007:15;54026:28;54045:8;54026:18;:28::i;:::-;53994:60;;-1:-1:-1;53994:60:0;-1:-1:-1;;;;;;54069:16:0;;54065:69;;54115:6;54102:20;;54065:69;54146:11;54160:16;54167:8;54160:6;:16::i;:::-;54146:30;;54196:34;54206:11;54219:2;54223:6;54196:9;:34::i;:::-;54187:43;;54278:2;-1:-1:-1;;;;;54248:41:0;54265:11;54248:41;;;54282:6;54248:41;;;;5349:25:1;;5337:2;5322:18;;5203:177;54248:41:0;;;;;;;;53983:314;;;53883:414;;;;:::o;55308:1859::-;55446:12;55460:10;55472:15;55489:27;55518:17;55539:35;55565:8;55539:25;:35::i;:::-;55445:129;;;;;;;;;;55587:13;55603:15;:28;55619:11;55603:28;;;;;;;;;;;;;;;55632:11;55603:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55603:49:0;;;;;;;;;;;;;;-1:-1:-1;55677:16:0;55684:8;55677:6;:16::i;:::-;55663:30;;55821:8;55816:167;;55855:45;55865:11;55886:4;55893:6;55855:9;:45::i;:::-;55915:28;;;;;;;:15;:28;;;;;;;:41;;55846:54;;-1:-1:-1;55967:4:0;;55915:41;;55944:11;;55915:41;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55915:49:0;;;;;;;;;;:56;;-1:-1:-1;;55915:56:0;;;;;;;;;;55816:167;-1:-1:-1;;;;;57261:20:0;;;55995:97;;56037:22;;-1:-1:-1;;;;;10165:32:1;;10147:51;;56037:22:0;;10135:2:1;10120:18;56037:22:0;;;;;;;56074:7;;;;;;;;;55995:97;56166:11;56214;56251:6;56291:8;56326:4;56355:2;56383:6;56431:14;56146:17;56516:8;:33;;56539:10;-1:-1:-1;;;;;56516:33:0;;;;56527:9;56516:33;56505:44;;56561:12;56575:19;56598:230;56646:9;56670:3;56711:31;;;56744:10;56756;56768:5;56775;56782:3;56787:7;56796:15;56813:3;56688:129;;;;;;;;;;;;;;;:::i;56598:230::-;56560:268;;;;56845:7;56841:319;;;56884:18;;;;;;56922:59;;;;;;;;;;56957:10;;56969:5;;56884:18;;56922:59;:::i;:::-;;;;;;;;56854:139;56841:319;;;57081:67;57101:10;57113;57125:5;57132:7;57141:6;57081:19;:67::i;:::-;55434:1733;;;;;;;;;;;;;;;;;;55308:1859;;;;;:::o;82722:177::-;82832:58;;-1:-1:-1;;;;;39824:32:1;;82832:58:0;;;39806:51:1;39873:18;;;39866:34;;;82805:86:0;;82825:5;;-1:-1:-1;;;82855:23:0;39779:18:1;;82832:58:0;;;;-1:-1:-1;;82832:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;82832:58:0;-1:-1:-1;;;;;;82832:58:0;;;;;;;;;;82805:19;:86::i;:::-;82722:177;;;:::o;83144:205::-;83272:68;;-1:-1:-1;;;;;40169:15:1;;;83272:68:0;;;40151:34:1;40221:15;;40201:18;;;40194:43;40253:18;;;40246:34;;;83245:96:0;;83265:5;;-1:-1:-1;;;83295:27:0;40086:18:1;;83272:68:0;39911:375:1;33674:271:0;33756:13;33815:2;33790:14;:21;:27;;33782:68;;;;-1:-1:-1;;;33782:68:0;;40493:2:1;33782:68:0;;;40475:21:1;40532:2;40512:18;;;40505:30;40571;40551:18;;;40544:58;40619:18;;33782:68:0;40291:352:1;33782:68:0;-1:-1:-1;33923:2:0;33903:23;33897:30;;33674:271::o;57547:121::-;57612:4;57636:24;91902:9;-1:-1:-1;;;;;57636:24:0;;;:::i;33953:402::-;34076:35;;;34052:21;34076:35;;;:22;:35;;;;;;;34126:21;;;34122:138;;-1:-1:-1;30881:5:0;34122:138;34294:16;34278:12;:32;;34270:77;;;;-1:-1:-1;;;34270:77:0;;40850:2:1;34270:77:0;;;40832:21:1;;;40869:18;;;40862:30;40928:34;40908:18;;;40901:62;40980:18;;34270:77:0;40648:356:1;58059:343:0;58141:10;;;58189:19;:8;58141:10;58189:16;:19::i;:::-;:30;;;:55;;;;;58223:8;:15;58242:2;58223:21;58189:55;58181:92;;;;-1:-1:-1;;;58181:92:0;;41211:2:1;58181:92:0;;;41193:21:1;41250:2;41230:18;;;41223:30;-1:-1:-1;;;41269:18:1;;;41262:54;41333:18;;58181:92:0;41009:348:1;58181:92:0;58291:22;:8;58310:2;58291:18;:22::i;:::-;58286:27;-1:-1:-1;58373:21:0;:8;58391:2;58373:17;:21::i;:::-;58362:32;;58059:343;;;:::o;91028:373::-;91124:4;91159:7;91141:14;;:25;;;;;;;:::i;:::-;;;;-1:-1:-1;;91277:4:0;-1:-1:-1;;;;;91255:27:0;;;91251:74;;-1:-1:-1;91306:7:0;91299:14;;91251:74;91344:49;91366:4;91373:10;91385:7;91344:13;:49::i;58784:557::-;58889:12;;;58932:20;58889:12;49295:1;58995:19;:8;58889:12;58995:16;:19::i;:::-;:39;;;58987:76;;;;-1:-1:-1;;;58987:76:0;;41211:2:1;58987:76:0;;;41193:21:1;41250:2;41230:18;;;41223:30;-1:-1:-1;;;41269:18:1;;;41262:54;41333:18;;58987:76:0;41009:348:1;58987:76:0;59081:22;:8;59100:2;59081:18;:22::i;:::-;59076:27;-1:-1:-1;59163:21:0;:8;59181:2;59163:17;:21::i;:::-;59152:32;-1:-1:-1;59202:22:0;:8;59221:2;59202:18;:22::i;:::-;59195:29;-1:-1:-1;59251:21:0;:8;59269:2;59251:17;:21::i;:::-;59235:37;;59293:40;59308:2;59330;59312:8;:15;:20;;;;:::i;:::-;59293:8;;:40;:14;:40::i;:::-;59283:50;;58784:557;;;;;;;:::o;87008:649::-;87432:23;87458:69;87486:4;87458:69;;;;;;;;;;;;;;;;;87466:5;-1:-1:-1;;;;;87458:27:0;;;:69;;;;;:::i;:::-;87432:95;;87546:10;:17;87567:1;87546:22;:56;;;;87583:10;87572:30;;;;;;;;;;;;:::i;:::-;87538:111;;;;-1:-1:-1;;;87538:111:0;;41814:2:1;87538:111:0;;;41796:21:1;41853:2;41833:18;;;41826:30;41892:34;41872:18;;;41865:62;-1:-1:-1;;;41943:18:1;;;41936:40;41993:19;;87538:111:0;41612:406:1;23386:360:0;23462:7;23507:11;:6;23516:2;23507:11;:::i;:::-;23490:6;:13;:28;;23482:62;;;;-1:-1:-1;;;23482:62:0;;42225:2:1;23482:62:0;;;42207:21:1;42264:2;42244:18;;;42237:30;-1:-1:-1;;;42283:18:1;;;42276:51;42344:18;;23482:62:0;42023:345:1;23482:62:0;-1:-1:-1;23636:30:0;23652:4;23636:30;23630:37;-1:-1:-1;;;23626:71:0;;;23386:360::o;24707:311::-;24782:6;24826:10;:6;24835:1;24826:10;:::i;:::-;24809:6;:13;:27;;24801:60;;;;-1:-1:-1;;;24801:60:0;;42575:2:1;24801:60:0;;;42557:21:1;42614:2;42594:18;;;42587:30;-1:-1:-1;;;42633:18:1;;;42626:50;42693:18;;24801:60:0;42373:344:1;24801:60:0;-1:-1:-1;24942:29:0;24958:3;24942:29;24936:36;;24707:311::o;25990:326::-;26066:7;26111:11;:6;26120:2;26111:11;:::i;:::-;26094:6;:13;:28;;26086:62;;;;-1:-1:-1;;;26086:62:0;;42924:2:1;26086:62:0;;;42906:21:1;42963:2;42943:18;;;42936:30;-1:-1:-1;;;42982:18:1;;;42975:51;43043:18;;26086:62:0;42722:345:1;26086:62:0;-1:-1:-1;26236:30:0;26252:4;26236:30;26230:37;;25990:326::o;76657:195::-;76760:12;76792:52;76814:6;76822:4;76828:1;76831:12;76760;77997;78011:23;78038:6;-1:-1:-1;;;;;78038:11:0;78057:5;78064:4;78038:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77996:73;;;;78087:69;78114:6;78122:7;78131:10;78143:12;78087:26;:69::i;:::-;78080:76;77709:455;-1:-1:-1;;;;;;;77709:455:0:o;80214:644::-;80399:12;80428:7;80424:427;;;80456:10;:17;80477:1;80456:22;80452:290;;-1:-1:-1;;;;;57261:20:0;;;80666:60;;;;-1:-1:-1;;;80666:60:0;;43681:2:1;80666:60:0;;;43663:21:1;43720:2;43700:18;;;43693:30;43759:31;43739:18;;;43732:59;43808:18;;80666:60:0;43479:353:1;80666:60:0;-1:-1:-1;80763:10:0;80756:17;;80424:427;80806:33;80814:10;80826:12;81527:17;;:21;81523:388;;81759:10;81753:17;81816:15;81803:10;81799:2;81795:19;81788:44;81523:388;81886:12;81879:20;;-1:-1:-1;;;81879:20:0;;;;;;;;:::i;14:159:1:-;81:20;;141:6;130:18;;120:29;;110:57;;163:1;160;153:12;110:57;14:159;;;:::o;178:347::-;229:8;239:6;293:3;286:4;278:6;274:17;270:27;260:55;;311:1;308;301:12;260:55;-1:-1:-1;334:20:1;;-1:-1:-1;;;;;366:30:1;;363:50;;;409:1;406;399:12;363:50;446:4;438:6;434:17;422:29;;498:3;491:4;482:6;474;470:19;466:30;463:39;460:59;;;515:1;512;505:12;460:59;178:347;;;;;:::o;530:171::-;597:20;;-1:-1:-1;;;;;646:30:1;;636:41;;626:69;;691:1;688;681:12;706:862;812:6;820;828;836;844;852;905:3;893:9;884:7;880:23;876:33;873:53;;;922:1;919;912:12;873:53;945:28;963:9;945:28;:::i;:::-;935:38;;1024:2;1013:9;1009:18;996:32;-1:-1:-1;;;;;1088:2:1;1080:6;1077:14;1074:34;;;1104:1;1101;1094:12;1074:34;1143:58;1193:7;1184:6;1173:9;1169:22;1143:58;:::i;:::-;1220:8;;-1:-1:-1;1117:84:1;-1:-1:-1;1117:84:1;;-1:-1:-1;1274:37:1;1307:2;1292:18;;1274:37;:::i;:::-;1264:47;;1364:2;1353:9;1349:18;1336:32;1320:48;;1393:2;1383:8;1380:16;1377:36;;;1409:1;1406;1399:12;1377:36;;1448:60;1500:7;1489:8;1478:9;1474:24;1448:60;:::i;:::-;706:862;;;;-1:-1:-1;706:862:1;;-1:-1:-1;706:862:1;;1527:8;;706:862;-1:-1:-1;;;706:862:1:o;1573:286::-;1631:6;1684:2;1672:9;1663:7;1659:23;1655:32;1652:52;;;1700:1;1697;1690:12;1652:52;1726:23;;-1:-1:-1;;;;;;1778:32:1;;1768:43;;1758:71;;1825:1;1822;1815:12;2056:184;2114:6;2167:2;2155:9;2146:7;2142:23;2138:32;2135:52;;;2183:1;2180;2173:12;2135:52;2206:28;2224:9;2206:28;:::i;2245:252::-;2312:6;2320;2373:2;2361:9;2352:7;2348:23;2344:32;2341:52;;;2389:1;2386;2379:12;2341:52;2412:28;2430:9;2412:28;:::i;:::-;2402:38;2487:2;2472:18;;;;2459:32;;-1:-1:-1;;;2245:252:1:o;2502:131::-;-1:-1:-1;;;;;2577:31:1;;2567:42;;2557:70;;2623:1;2620;2613:12;2638:160;2703:5;2748:2;2739:6;2734:3;2730:16;2726:25;2723:45;;;2764:1;2761;2754:12;2723:45;-1:-1:-1;2786:6:1;2638:160;-1:-1:-1;2638:160:1:o;2803:780::-;2938:6;2946;2954;2962;2970;2978;3031:3;3019:9;3010:7;3006:23;3002:33;2999:53;;;3048:1;3045;3038:12;2999:53;3087:9;3074:23;3106:31;3131:5;3106:31;:::i;:::-;3156:5;-1:-1:-1;3180:37:1;3213:2;3198:18;;3180:37;:::i;:::-;3170:47;;3264:2;3253:9;3249:18;3236:32;3226:42;;3315:2;3304:9;3300:18;3287:32;3277:42;;3366:3;3355:9;3351:19;3338:33;3328:43;;3422:3;3411:9;3407:19;3394:33;-1:-1:-1;;;;;3442:6:1;3439:30;3436:50;;;3482:1;3479;3472:12;3436:50;3505:72;3569:7;3560:6;3549:9;3545:22;3505:72;:::i;:::-;3495:82;;;2803:780;;;;;;;;:::o;3588:118::-;3674:5;3667:13;3660:21;3653:5;3650:32;3640:60;;3696:1;3693;3686:12;3711:748;3813:6;3821;3829;3837;3845;3853;3906:3;3894:9;3885:7;3881:23;3877:33;3874:53;;;3923:1;3920;3913:12;3874:53;3946:28;3964:9;3946:28;:::i;:::-;3936:38;;4021:2;4010:9;4006:18;3993:32;3983:42;;4072:2;4061:9;4057:18;4044:32;4034:42;;4126:2;4115:9;4111:18;4098:32;4139:28;4161:5;4139:28;:::i;:::-;4186:5;-1:-1:-1;4242:3:1;4227:19;;4214:33;-1:-1:-1;;;;;4259:30:1;;4256:50;;;4302:1;4299;4292:12;4256:50;4341:58;4391:7;4382:6;4371:9;4367:22;4341:58;:::i;4717:481::-;4795:6;4803;4811;4864:2;4852:9;4843:7;4839:23;4835:32;4832:52;;;4880:1;4877;4870:12;4832:52;4903:28;4921:9;4903:28;:::i;:::-;4893:38;;4982:2;4971:9;4967:18;4954:32;-1:-1:-1;;;;;5001:6:1;4998:30;4995:50;;;5041:1;5038;5031:12;4995:50;5080:58;5130:7;5121:6;5110:9;5106:22;5080:58;:::i;:::-;4717:481;;5157:8;;-1:-1:-1;5054:84:1;;-1:-1:-1;;;;4717:481:1:o;5385:1162::-;5548:6;5556;5564;5572;5580;5588;5596;5604;5612;5665:3;5653:9;5644:7;5640:23;5636:33;5633:53;;;5682:1;5679;5672:12;5633:53;5721:9;5708:23;5740:31;5765:5;5740:31;:::i;:::-;5790:5;-1:-1:-1;5814:37:1;5847:2;5832:18;;5814:37;:::i;:::-;5804:47;;5898:2;5887:9;5883:18;5870:32;5860:42;;5949:2;5938:9;5934:18;5921:32;5911:42;;6000:3;5989:9;5985:19;5972:33;5962:43;;6056:3;6045:9;6041:19;6028:33;-1:-1:-1;;;;;6121:2:1;6113:6;6110:14;6107:34;;;6137:1;6134;6127:12;6107:34;6176:58;6226:7;6217:6;6206:9;6202:22;6176:58;:::i;:::-;6253:8;;-1:-1:-1;6150:84:1;-1:-1:-1;6150:84:1;;-1:-1:-1;6307:38:1;6340:3;6325:19;;6307:38;:::i;:::-;6297:48;;6398:3;6387:9;6383:19;6370:33;6354:49;;6428:2;6418:8;6415:16;6412:36;;;6444:1;6441;6434:12;6412:36;;6467:74;6533:7;6522:8;6511:9;6507:24;6467:74;:::i;:::-;6457:84;;;5385:1162;;;;;;;;;;;:::o;6552:247::-;6611:6;6664:2;6652:9;6643:7;6639:23;6635:32;6632:52;;;6680:1;6677;6670:12;6632:52;6719:9;6706:23;6738:31;6763:5;6738:31;:::i;6993:127::-;7054:10;7049:3;7045:20;7042:1;7035:31;7085:4;7082:1;7075:15;7109:4;7106:1;7099:15;7125:275;7196:2;7190:9;7261:2;7242:13;;-1:-1:-1;;7238:27:1;7226:40;;-1:-1:-1;;;;;7281:34:1;;7317:22;;;7278:62;7275:88;;;7343:18;;:::i;:::-;7379:2;7372:22;7125:275;;-1:-1:-1;7125:275:1:o;7405:186::-;7453:4;-1:-1:-1;;;;;7478:6:1;7475:30;7472:56;;;7508:18;;:::i;:::-;-1:-1:-1;7574:2:1;7553:15;-1:-1:-1;;7549:29:1;7580:4;7545:40;;7405:186::o;7596:815::-;7680:6;7688;7696;7749:2;7737:9;7728:7;7724:23;7720:32;7717:52;;;7765:1;7762;7755:12;7717:52;7788:28;7806:9;7788:28;:::i;:::-;7778:38;;7867:2;7856:9;7852:18;7839:32;-1:-1:-1;;;;;7886:6:1;7883:30;7880:50;;;7926:1;7923;7916:12;7880:50;7949:22;;8002:4;7994:13;;7990:27;-1:-1:-1;7980:55:1;;8031:1;8028;8021:12;7980:55;8067:2;8054:16;8092:48;8108:31;8136:2;8108:31;:::i;:::-;8092:48;:::i;:::-;8163:2;8156:5;8149:17;8203:7;8198:2;8193;8189;8185:11;8181:20;8178:33;8175:53;;;8224:1;8221;8214:12;8175:53;8279:2;8274;8270;8266:11;8261:2;8254:5;8250:14;8237:45;8323:1;8318:2;8313;8306:5;8302:14;8298:23;8291:34;8344:5;8334:15;;;;;8368:37;8401:2;8390:9;8386:18;8368:37;:::i;:::-;8358:47;;7596:815;;;;;:::o;8598:250::-;8683:1;8693:113;8707:6;8704:1;8701:13;8693:113;;;8783:11;;;8777:18;8764:11;;;8757:39;8729:2;8722:10;8693:113;;;-1:-1:-1;;8840:1:1;8822:16;;8815:27;8598:250::o;8853:270::-;8894:3;8932:5;8926:12;8959:6;8954:3;8947:19;8975:76;9044:6;9037:4;9032:3;9028:14;9021:4;9014:5;9010:16;8975:76;:::i;:::-;9105:2;9084:15;-1:-1:-1;;9080:29:1;9071:39;;;;9112:4;9067:50;;8853:270;-1:-1:-1;;8853:270:1:o;9128:217::-;9275:2;9264:9;9257:21;9238:4;9295:44;9335:2;9324:9;9320:18;9312:6;9295:44;:::i;9350:385::-;9422:6;9430;9438;9491:2;9479:9;9470:7;9466:23;9462:32;9459:52;;;9507:1;9504;9497:12;9459:52;9530:28;9548:9;9530:28;:::i;:::-;9520:38;;9608:2;9597:9;9593:18;9580:32;9621:28;9643:5;9621:28;:::i;:::-;9668:5;-1:-1:-1;9692:37:1;9725:2;9710:18;;9692:37;:::i;9740:256::-;9806:6;9814;9867:2;9855:9;9846:7;9842:23;9838:32;9835:52;;;9883:1;9880;9873:12;9835:52;9906:28;9924:9;9906:28;:::i;:::-;9896:38;;9953:37;9986:2;9975:9;9971:18;9953:37;:::i;:::-;9943:47;;9740:256;;;;;:::o;10209:1130::-;10339:6;10347;10355;10363;10371;10379;10387;10395;10403;10456:3;10444:9;10435:7;10431:23;10427:33;10424:53;;;10473:1;10470;10463:12;10424:53;10496:28;10514:9;10496:28;:::i;:::-;10486:38;;10571:2;10560:9;10556:18;10543:32;10533:42;;10622:2;10611:9;10607:18;10594:32;10584:42;;10677:2;10666:9;10662:18;10649:32;-1:-1:-1;;;;;10741:2:1;10733:6;10730:14;10727:34;;;10757:1;10754;10747:12;10727:34;10796:58;10846:7;10837:6;10826:9;10822:22;10796:58;:::i;:::-;10873:8;;-1:-1:-1;10770:84:1;-1:-1:-1;10770:84:1;;-1:-1:-1;10927:38:1;10960:3;10945:19;;10927:38;:::i;:::-;10917:48;;11015:3;11004:9;11000:19;10987:33;10974:46;;11029:28;11051:5;11029:28;:::i;:::-;11076:5;;-1:-1:-1;11134:3:1;11119:19;;11106:33;;11151:16;;;11148:36;;;11180:1;11177;11170:12;11148:36;;11219:60;11271:7;11260:8;11249:9;11245:24;11219:60;:::i;:::-;11193:86;;11298:8;11288:18;;;11325:8;11315:18;;;10209:1130;;;;;;;;;;;:::o;11852:622::-;11947:6;11955;11963;11971;11979;12032:3;12020:9;12011:7;12007:23;12003:33;12000:53;;;12049:1;12046;12039:12;12000:53;12072:28;12090:9;12072:28;:::i;:::-;12062:38;;12119:37;12152:2;12141:9;12137:18;12119:37;:::i;:::-;12109:47;;12203:2;12192:9;12188:18;12175:32;12165:42;;12258:2;12247:9;12243:18;12230:32;-1:-1:-1;;;;;12277:6:1;12274:30;12271:50;;;12317:1;12314;12307:12;12271:50;12356:58;12406:7;12397:6;12386:9;12382:22;12356:58;:::i;:::-;11852:622;;;;-1:-1:-1;11852:622:1;;-1:-1:-1;12433:8:1;;12330:84;11852:622;-1:-1:-1;;;11852:622:1:o;12672:324::-;12747:6;12755;12763;12816:2;12804:9;12795:7;12791:23;12787:32;12784:52;;;12832:1;12829;12822:12;12784:52;12855:28;12873:9;12855:28;:::i;:::-;12845:38;;12902:37;12935:2;12924:9;12920:18;12902:37;:::i;:::-;12892:47;;12986:2;12975:9;12971:18;12958:32;12948:42;;12672:324;;;;;:::o;13001:1205::-;13143:6;13151;13159;13167;13175;13183;13191;13199;13207;13215;13268:3;13256:9;13247:7;13243:23;13239:33;13236:53;;;13285:1;13282;13275:12;13236:53;13308:28;13326:9;13308:28;:::i;:::-;13298:38;;13387:2;13376:9;13372:18;13359:32;-1:-1:-1;;;;;13451:2:1;13443:6;13440:14;13437:34;;;13467:1;13464;13457:12;13437:34;13506:58;13556:7;13547:6;13536:9;13532:22;13506:58;:::i;:::-;13583:8;;-1:-1:-1;13480:84:1;-1:-1:-1;13480:84:1;;-1:-1:-1;13637:37:1;13670:2;13655:18;;13637:37;:::i;:::-;13627:47;;13721:2;13710:9;13706:18;13693:32;13683:42;;13775:3;13764:9;13760:19;13747:33;13734:46;;13789:31;13814:5;13789:31;:::i;:::-;13839:5;;-1:-1:-1;13891:3:1;13876:19;;13863:33;;-1:-1:-1;13949:3:1;13934:19;;13921:33;;13966:16;;;13963:36;;;13995:1;13992;13985:12;13963:36;;14034:60;14086:7;14075:8;14064:9;14060:24;14034:60;:::i;:::-;14008:86;;14113:8;14103:18;;;14140:8;14130:18;;;14195:3;14184:9;14180:19;14167:33;14157:43;;13001:1205;;;;;;;;;;;;;:::o;14211:460::-;14295:6;14303;14311;14319;14372:3;14360:9;14351:7;14347:23;14343:33;14340:53;;;14389:1;14386;14379:12;14340:53;14412:28;14430:9;14412:28;:::i;:::-;14402:38;;14459:37;14492:2;14481:9;14477:18;14459:37;:::i;:::-;14449:47;;14546:2;14535:9;14531:18;14518:32;14559:31;14584:5;14559:31;:::i;:::-;14211:460;;;;-1:-1:-1;14609:5:1;;14661:2;14646:18;14633:32;;-1:-1:-1;;14211:460:1:o;15035:380::-;15114:1;15110:12;;;;15157;;;15178:61;;15232:4;15224:6;15220:17;15210:27;;15178:61;15285:2;15277:6;15274:14;15254:18;15251:38;15248:161;;15331:10;15326:3;15322:20;15319:1;15312:31;15366:4;15363:1;15356:15;15394:4;15391:1;15384:15;15420:271;15603:6;15595;15590:3;15577:33;15559:3;15629:16;;15654:13;;;15629:16;15420:271;-1:-1:-1;15420:271:1:o;16363:521::-;16440:4;16446:6;16506:11;16493:25;16600:2;16596:7;16585:8;16569:14;16565:29;16561:43;16541:18;16537:68;16527:96;;16619:1;16616;16609:12;16527:96;16646:33;;16698:20;;;-1:-1:-1;;;;;;16730:30:1;;16727:50;;;16773:1;16770;16763:12;16727:50;16806:4;16794:17;;-1:-1:-1;16837:14:1;16833:27;;;16823:38;;16820:58;;;16874:1;16871;16864:12;16889:409;17091:2;17073:21;;;17130:2;17110:18;;;17103:30;17169:34;17164:2;17149:18;;17142:62;-1:-1:-1;;;17235:2:1;17220:18;;17213:43;17288:3;17273:19;;16889:409::o;17303:266::-;17391:6;17386:3;17379:19;17443:6;17436:5;17429:4;17424:3;17420:14;17407:43;-1:-1:-1;17495:1:1;17470:16;;;17488:4;17466:27;;;17459:38;;;;17551:2;17530:15;;;-1:-1:-1;;17526:29:1;17517:39;;;17513:50;;17303:266::o;17574:326::-;17769:6;17761;17757:19;17746:9;17739:38;17813:2;17808;17797:9;17793:18;17786:30;17720:4;17833:61;17890:2;17879:9;17875:18;17867:6;17859;17833:61;:::i;18260:401::-;18462:2;18444:21;;;18501:2;18481:18;;;18474:30;18540:34;18535:2;18520:18;;18513:62;-1:-1:-1;;;18606:2:1;18591:18;;18584:35;18651:3;18636:19;;18260:401::o;19446:184::-;19516:6;19569:2;19557:9;19548:7;19544:23;19540:32;19537:52;;;19585:1;19582;19575:12;19537:52;-1:-1:-1;19608:16:1;;19446:184;-1:-1:-1;19446:184:1:o;19635:127::-;19696:10;19691:3;19687:20;19684:1;19677:31;19727:4;19724:1;19717:15;19751:4;19748:1;19741:15;19767:128;19834:9;;;19855:11;;;19852:37;;;19869:18;;:::i;20258:360::-;20469:6;20461;20456:3;20443:33;20539:2;20535:15;;;;-1:-1:-1;;20531:53:1;20495:16;;20520:65;;;20609:2;20601:11;;20258:360;-1:-1:-1;20258:360:1:o;20748:544::-;20849:2;20844:3;20841:11;20838:448;;;20885:1;20910:5;20906:2;20899:17;20955:4;20951:2;20941:19;21025:2;21013:10;21009:19;21006:1;21002:27;20996:4;20992:38;21061:4;21049:10;21046:20;21043:47;;;-1:-1:-1;21084:4:1;21043:47;21139:2;21134:3;21130:12;21127:1;21123:20;21117:4;21113:31;21103:41;;21194:82;21212:2;21205:5;21202:13;21194:82;;;21257:17;;;21238:1;21227:13;21194:82;;21468:1348;21592:3;21586:10;-1:-1:-1;;;;;21611:6:1;21608:30;21605:56;;;21641:18;;:::i;:::-;21670:96;21759:6;21719:38;21751:4;21745:11;21719:38;:::i;:::-;21713:4;21670:96;:::i;:::-;21821:4;;21885:2;21874:14;;21902:1;21897:662;;;;22603:1;22620:6;22617:89;;;-1:-1:-1;22672:19:1;;;22666:26;22617:89;-1:-1:-1;;21425:1:1;21421:11;;;21417:24;21413:29;21403:40;21449:1;21445:11;;;21400:57;22719:81;;21867:943;;21897:662;20695:1;20688:14;;;20732:4;20719:18;;-1:-1:-1;;21933:20:1;;;22050:236;22064:7;22061:1;22058:14;22050:236;;;22153:19;;;22147:26;22132:42;;22245:27;;;;22213:1;22201:14;;;;22080:19;;22050:236;;;22054:3;22314:6;22305:7;22302:19;22299:201;;;22375:19;;;22369:26;-1:-1:-1;;22458:1:1;22454:14;;;22470:3;22450:24;22446:37;22442:42;22427:58;22412:74;;22299:201;-1:-1:-1;;;;;22546:1:1;22530:14;;;22526:22;22513:36;;-1:-1:-1;21468:1348:1:o;22821:498::-;23021:4;23050:6;23095:2;23087:6;23083:15;23072:9;23065:34;23147:2;23139:6;23135:15;23130:2;23119:9;23115:18;23108:43;;23187:6;23182:2;23171:9;23167:18;23160:34;23230:3;23225:2;23214:9;23210:18;23203:31;23251:62;23308:3;23297:9;23293:19;23285:6;23277;23251:62;:::i;24130:493::-;24379:6;24371;24367:19;24356:9;24349:38;24423:3;24418:2;24407:9;24403:18;24396:31;24330:4;24444:62;24501:3;24490:9;24486:19;24478:6;24470;24444:62;:::i;:::-;-1:-1:-1;;;;;24542:31:1;;;;24537:2;24522:18;;24515:59;-1:-1:-1;24605:2:1;24590:18;24583:34;24436:70;24130:493;-1:-1:-1;;;24130:493:1:o;25351:753::-;25684:6;25676;25672:19;25661:9;25654:38;25728:3;25723:2;25712:9;25708:18;25701:31;25635:4;25755:62;25812:3;25801:9;25797:19;25789:6;25781;25755:62;:::i;:::-;-1:-1:-1;;;;;25857:6:1;25853:31;25848:2;25837:9;25833:18;25826:59;25921:6;25916:2;25905:9;25901:18;25894:34;25965:6;25959:3;25948:9;25944:19;25937:35;26021:9;26013:6;26009:22;26003:3;25992:9;25988:19;25981:51;26049:49;26091:6;26083;26075;26049:49;:::i;:::-;26041:57;25351:753;-1:-1:-1;;;;;;;;;;;25351:753:1:o;26109:1202::-;-1:-1:-1;;;;;26226:3:1;26223:27;26220:53;;;26253:18;;:::i;:::-;26282:93;26371:3;26331:38;26363:4;26357:11;26331:38;:::i;:::-;26325:4;26282:93;:::i;:::-;26401:1;26426:2;26421:3;26418:11;26443:1;26438:615;;;;27097:1;27114:3;27111:93;;;-1:-1:-1;27170:19:1;;;27157:33;27111:93;-1:-1:-1;;21425:1:1;21421:11;;;21417:24;21413:29;21403:40;21449:1;21445:11;;;21400:57;27217:78;;26411:894;;26438:615;20695:1;20688:14;;;20732:4;20719:18;;-1:-1:-1;;26474:17:1;;;26574:9;26596:229;26610:7;26607:1;26604:14;26596:229;;;26699:19;;;26686:33;26671:49;;26806:4;26791:20;;;;26759:1;26747:14;;;;26626:12;26596:229;;;26600:3;26853;26844:7;26841:16;26838:159;;;26977:1;26973:6;26967:3;26961;26958:1;26954:11;26950:21;26946:34;26942:39;26929:9;26924:3;26920:19;26907:33;26903:79;26895:6;26888:95;26838:159;;;27040:1;27034:3;27031:1;27027:11;27023:19;27017:4;27010:33;26411:894;;26109:1202;;;:::o;27316:168::-;27389:9;;;27420;;27437:15;;;27431:22;;27417:37;27407:71;;27458:18;;:::i;27489:127::-;27550:10;27545:3;27541:20;27538:1;27531:31;27581:4;27578:1;27571:15;27605:4;27602:1;27595:15;27621:120;27661:1;27687;27677:35;;27692:18;;:::i;:::-;-1:-1:-1;27726:9:1;;27621:120::o;28614:647::-;28693:6;28746:2;28734:9;28725:7;28721:23;28717:32;28714:52;;;28762:1;28759;28752:12;28714:52;28795:9;28789:16;-1:-1:-1;;;;;28820:6:1;28817:30;28814:50;;;28860:1;28857;28850:12;28814:50;28883:22;;28936:4;28928:13;;28924:27;-1:-1:-1;28914:55:1;;28965:1;28962;28955:12;28914:55;28994:2;28988:9;29019:48;29035:31;29063:2;29035:31;:::i;29019:48::-;29090:2;29083:5;29076:17;29130:7;29125:2;29120;29116;29112:11;29108:20;29105:33;29102:53;;;29151:1;29148;29141:12;29102:53;29164:67;29228:2;29223;29216:5;29212:14;29207:2;29203;29199:11;29164:67;:::i;29266:555::-;29523:6;29515;29511:19;29500:9;29493:38;29567:3;29562:2;29551:9;29547:18;29540:31;29474:4;29594:45;29634:3;29623:9;29619:19;29611:6;29594:45;:::i;:::-;-1:-1:-1;;;;;29679:6:1;29675:31;29670:2;29659:9;29655:18;29648:59;29755:9;29747:6;29743:22;29738:2;29727:9;29723:18;29716:50;29783:32;29808:6;29800;29783:32;:::i;30541:640::-;30822:6;30810:19;;30792:38;;-1:-1:-1;;;;;30866:32:1;;30861:2;30846:18;;30839:60;30886:3;30930:2;30915:18;;30908:31;;;-1:-1:-1;;30962:45:1;;30987:19;;30979:6;30962:45;:::i;:::-;31057:6;31050:14;31043:22;31038:2;31027:9;31023:18;31016:50;31115:9;31107:6;31103:22;31097:3;31086:9;31082:19;31075:51;31143:32;31168:6;31160;31143:32;:::i;:::-;31135:40;30541:640;-1:-1:-1;;;;;;;;30541:640:1:o;31186:245::-;31265:6;31273;31326:2;31314:9;31305:7;31301:23;31297:32;31294:52;;;31342:1;31339;31332:12;31294:52;-1:-1:-1;;31365:16:1;;31421:2;31406:18;;;31400:25;31365:16;;31400:25;;-1:-1:-1;31186:245:1:o;31793:125::-;31858:9;;;31879:10;;;31876:36;;;31892:18;;:::i;32612:287::-;32741:3;32779:6;32773:13;32795:66;32854:6;32849:3;32842:4;32834:6;32830:17;32795:66;:::i;:::-;32877:16;;;;;32612:287;-1:-1:-1;;32612:287:1:o;32904:716::-;33207:6;33199;33195:19;33184:9;33177:38;33251:3;33246:2;33235:9;33231:18;33224:31;33158:4;33278:45;33318:3;33307:9;33303:19;33295:6;33278:45;:::i;:::-;-1:-1:-1;;;;;33363:6:1;33359:31;33354:2;33343:9;33339:18;33332:59;33439:9;33431:6;33427:22;33422:2;33411:9;33407:18;33400:50;33473:32;33498:6;33490;33473:32;:::i;:::-;33459:46;;33554:9;33546:6;33542:22;33536:3;33525:9;33521:19;33514:51;33582:32;33607:6;33599;33582:32;:::i;34336:112::-;34368:1;34394;34384:35;;34399:18;;:::i;:::-;-1:-1:-1;34433:9:1;;34336:112::o;36429:837::-;36778:6;36770;36766:19;36755:9;36748:38;36822:3;36817:2;36806:9;36802:18;36795:31;36729:4;36849:45;36889:3;36878:9;36874:19;36866:6;36849:45;:::i;:::-;36942:9;36934:6;36930:22;36925:2;36914:9;36910:18;36903:50;36976:32;37001:6;36993;36976:32;:::i;:::-;-1:-1:-1;;;;;37082:15:1;;;37077:2;37062:18;;37055:43;37135:15;;37129:3;37114:19;;37107:44;37188:22;;;37035:3;37167:19;;37160:51;36962:46;-1:-1:-1;37228:32:1;36962:46;37245:6;37228:32;:::i;:::-;37220:40;36429:837;-1:-1:-1;;;;;;;;;36429:837:1:o;37271:727::-;37593:3;37588;37584:13;37575:6;37570:3;37566:16;37562:36;37557:3;37550:49;37628:6;37624:1;37619:3;37615:11;37608:27;37532:3;-1:-1:-1;;;;;37658:3:1;37654:28;37734:2;37725:6;37720:3;37716:16;37712:25;37707:2;37702:3;37698:12;37691:47;37768:6;37763:2;37758:3;37754:12;37747:28;37827:2;37818:6;37813:3;37809:16;37805:25;37800:2;37795:3;37791:12;37784:47;;37860:6;37854:13;37876:75;37944:6;37939:2;37934:3;37930:12;37923:4;37915:6;37911:17;37876:75;:::i;:::-;37971:16;;;;37989:2;37967:25;;37271:727;-1:-1:-1;;;;;;;37271:727:1:o;38351:889::-;38671:4;38700:3;38742:6;38734;38730:19;38719:9;38712:38;38786:2;38781;38770:9;38766:18;38759:30;38812:44;38852:2;38841:9;38837:18;38829:6;38812:44;:::i;:::-;-1:-1:-1;;;;;38892:31:1;;38887:2;38872:18;;38865:59;38955:2;38940:18;;38933:34;;;-1:-1:-1;;;;;39004:32:1;;38998:3;38983:19;;38976:61;39024:3;39053:19;;39046:35;;;39118:22;;;39112:3;39097:19;;39090:51;38798:58;-1:-1:-1;39158:32:1;38798:58;39175:6;39158:32;:::i;:::-;39150:40;;;39227:6;39221:3;39210:9;39206:19;39199:35;38351:889;;;;;;;;;;;:::o;39245:382::-;39446:2;39435:9;39428:21;39409:4;39466:44;39506:2;39495:9;39491:18;39483:6;39466:44;:::i;:::-;-1:-1:-1;;;;;39546:31:1;;;;39541:2;39526:18;;39519:59;-1:-1:-1;39609:2:1;39594:18;39587:34;39458:52;39245:382;-1:-1:-1;39245:382:1:o;41362:245::-;41429:6;41482:2;41470:9;41461:7;41457:23;41453:32;41450:52;;;41498:1;41495;41488:12;41450:52;41530:9;41524:16;41549:28;41571:5;41549:28;:::i

Swarm Source

ipfs://4495807a73f54df216e7031f0d93c92bdc992182a5b4b976b789686dedbed272
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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