ETH Price: $3,439.05 (-1.29%)

Token

Fanko Official Token (raz)
 

Overview

Max Total Supply

306,905,581.122601 raz

Holders

1,064

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
drdefi.eth
Balance
327,046.741054653159725609 raz

Value
$0.00
0x8c9ec6a671c6819e84fb325604f73e321af0b5e3
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:
RazOFTNoTax

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 20000 runs

Other Settings:
paris EvmVersion, MIT license
File 1 of 40 : RazOFTNoTax.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {OFT} from "@layerzerolabs/oft-evm/contracts/OFT.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";

contract RazOFTNoTax is OFT {
    using Math for uint256;

    uint256 private constant FEE_BPS_SCALE = 10_000;
    uint256 private constant FEE_BPS = 100; // 1%

    constructor(address _lzEndpoint, address _delegate)
        OFT("Fanko Official Token", "raz", _lzEndpoint, _delegate)
        Ownable(_delegate)
    {}
}

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

File 3 of 40 : OFT.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IOFT, OFTCore } from "./OFTCore.sol";

/**
 * @title OFT Contract
 * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
 */
abstract contract OFT is OFTCore, ERC20 {
    /**
     * @dev Constructor for the OFT contract.
     * @param _name The name of the OFT.
     * @param _symbol The symbol of the OFT.
     * @param _lzEndpoint The LayerZero endpoint address.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(
        string memory _name,
        string memory _symbol,
        address _lzEndpoint,
        address _delegate
    ) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {}

    /**
     * @dev Retrieves the address of the underlying ERC20 implementation.
     * @return The address of the OFT token.
     *
     * @dev In the case of OFT, address(this) and erc20 are the same contract.
     */
    function token() public view returns (address) {
        return address(this);
    }

    /**
     * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
     * @return requiresApproval Needs approval of the underlying token implementation.
     *
     * @dev In the case of OFT where the contract IS the token, approval is NOT required.
     */
    function approvalRequired() external pure virtual returns (bool) {
        return false;
    }

    /**
     * @dev Burns tokens from the sender's specified balance.
     * @param _from The address to debit the tokens from.
     * @param _amountLD The amount of tokens to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @param _dstEid The destination chain ID.
     * @return amountSentLD The amount sent in local decimals.
     * @return amountReceivedLD The amount received in local decimals on the remote.
     */
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);

        // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90,
        // therefore amountSentLD CAN differ from amountReceivedLD.

        // @dev Default OFT burns on src.
        _burn(_from, amountSentLD);
    }

    /**
     * @dev Credits tokens to the specified address.
     * @param _to The address to credit the tokens to.
     * @param _amountLD The amount of tokens to credit in local decimals.
     * @dev _srcEid The source chain ID.
     * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 /*_srcEid*/
    ) internal virtual override returns (uint256 amountReceivedLD) {
        if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0)
        // @dev Default OFT mints on dst.
        _mint(_to, _amountLD);
        // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD.
        return _amountLD;
    }
}

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.20;

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

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

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

File 6 of 40 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 7 of 40 : OFTCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { OApp, Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OAppOptionsType3 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
import { IOAppMsgInspector } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol";

import { OAppPreCrimeSimulator } from "@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol";

import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol";
import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol";

/**
 * @title OFTCore
 * @dev Abstract contract for the OftChain (OFT) token.
 */
abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {
    using OFTMsgCodec for bytes;
    using OFTMsgCodec for bytes32;

    // @notice Provides a conversion rate when swapping between denominations of SD and LD
    //      - shareDecimals == SD == shared Decimals
    //      - localDecimals == LD == local decimals
    // @dev Considers that tokens have different decimal amounts on various chains.
    // @dev eg.
    //  For a token
    //      - locally with 4 decimals --> 1.2345 => uint(12345)
    //      - remotely with 2 decimals --> 1.23 => uint(123)
    //      - The conversion rate would be 10 ** (4 - 2) = 100
    //  @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,
    //  you can only display 1.23 -> uint(123).
    //  @dev To preserve the dust that would otherwise be lost on that conversion,
    //  we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh
    uint256 public immutable decimalConversionRate;

    // @notice Msg types that are used to identify the various OFT operations.
    // @dev This can be extended in child contracts for non-default oft operations
    // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.
    uint16 public constant SEND = 1;
    uint16 public constant SEND_AND_CALL = 2;

    // Address of an optional contract to inspect both 'message' and 'options'
    address public msgInspector;
    event MsgInspectorSet(address inspector);

    /**
     * @dev Constructor.
     * @param _localDecimals The decimals of the token on the local chain (this chain).
     * @param _endpoint The address of the LayerZero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {
        if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();
        decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());
    }

    /**
     * @notice Retrieves interfaceID and the version of the OFT.
     * @return interfaceId The interface ID.
     * @return version The version.
     *
     * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
     * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
     * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
     * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
     */
    function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {
        return (type(IOFT).interfaceId, 1);
    }

    /**
     * @dev Retrieves the shared decimals of the OFT.
     * @return The shared decimals of the OFT.
     *
     * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
     * Lowest common decimal denominator between chains.
     * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
     * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.
     * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615
     */
    function sharedDecimals() public view virtual returns (uint8) {
        return 6;
    }

    /**
     * @dev Sets the message inspector address for the OFT.
     * @param _msgInspector The address of the message inspector.
     *
     * @dev This is an optional contract that can be used to inspect both 'message' and 'options'.
     * @dev Set it to address(0) to disable it, or set it to a contract address to enable it.
     */
    function setMsgInspector(address _msgInspector) public virtual onlyOwner {
        msgInspector = _msgInspector;
        emit MsgInspectorSet(_msgInspector);
    }

    /**
     * @notice Provides a quote for OFT-related operations.
     * @param _sendParam The parameters for the send operation.
     * @return oftLimit The OFT limit information.
     * @return oftFeeDetails The details of OFT fees.
     * @return oftReceipt The OFT receipt information.
     */
    function quoteOFT(
        SendParam calldata _sendParam
    )
        external
        view
        virtual
        returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
    {
        uint256 minAmountLD = 0; // Unused in the default implementation.
        uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation.
        oftLimit = OFTLimit(minAmountLD, maxAmountLD);

        // Unused in the default implementation; reserved for future complex fee details.
        oftFeeDetails = new OFTFeeDetail[](0);

        // @dev This is the same as the send() operation, but without the actual send.
        // - amountSentLD is the amount in local decimals that would be sent from the sender.
        // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.
        // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.
        (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(
            _sendParam.amountLD,
            _sendParam.minAmountLD,
            _sendParam.dstEid
        );
        oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
    }

    /**
     * @notice Provides a quote for the send() operation.
     * @param _sendParam The parameters for the send() operation.
     * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
     * @return msgFee The calculated LayerZero messaging fee from the send() operation.
     *
     * @dev MessagingFee: LayerZero msg fee
     *  - nativeFee: The native fee.
     *  - lzTokenFee: The lzToken fee.
     */
    function quoteSend(
        SendParam calldata _sendParam,
        bool _payInLzToken
    ) external view virtual returns (MessagingFee memory msgFee) {
        // @dev mock the amount to receive, this is the same operation used in the send().
        // The quote is as similar as possible to the actual send() operation.
        (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);

        // @dev Builds the options and OFT message to quote in the endpoint.
        (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);

        // @dev Calculates the LayerZero fee for the send() operation.
        return _quote(_sendParam.dstEid, message, options, _payInLzToken);
    }

    /**
     * @dev Executes the send operation.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The calculated fee for the send() operation.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess funds.
     * @return msgReceipt The receipt for the send operation.
     * @return oftReceipt The OFT receipt information.
     *
     * @dev MessagingReceipt: LayerZero msg receipt
     *  - guid: The unique identifier for the sent message.
     *  - nonce: The nonce of the sent message.
     *  - fee: The LayerZero fee incurred for the message.
     */
    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata _fee,
        address _refundAddress
    ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
        // @dev Applies the token transfers regarding this send() operation.
        // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.
        // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.
        (uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
            msg.sender,
            _sendParam.amountLD,
            _sendParam.minAmountLD,
            _sendParam.dstEid
        );

        // @dev Builds the options and OFT message to quote in the endpoint.
        (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);

        // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
        msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
        // @dev Formulate the OFT receipt.
        oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);

        emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
    }

    /**
     * @dev Internal function to build the message and options.
     * @param _sendParam The parameters for the send() operation.
     * @param _amountLD The amount in local decimals.
     * @return message The encoded message.
     * @return options The encoded options.
     */
    function _buildMsgAndOptions(
        SendParam calldata _sendParam,
        uint256 _amountLD
    ) internal view virtual returns (bytes memory message, bytes memory options) {
        bool hasCompose;
        // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.
        (message, hasCompose) = OFTMsgCodec.encode(
            _sendParam.to,
            _toSD(_amountLD),
            // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.
            // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'
            _sendParam.composeMsg
        );
        // @dev Change the msg type depending if its composed or not.
        uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;
        // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.
        options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);

        // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.
        // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean
        address inspector = msgInspector; // caches the msgInspector to avoid potential double storage read
        if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);
    }

    /**
     * @dev Internal function to handle the receive on the LayerZero endpoint.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The encoded message.
     * @dev _executor The address of the executor.
     * @dev _extraData Additional data.
     */
    function _lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address /*_executor*/, // @dev unused in the default implementation.
        bytes calldata /*_extraData*/ // @dev unused in the default implementation.
    ) internal virtual override {
        // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)
        // Thus everything is bytes32() encoded in flight.
        address toAddress = _message.sendTo().bytes32ToAddress();
        // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals
        uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);

        if (_message.isComposed()) {
            // @dev Proprietary composeMsg format for the OFT.
            bytes memory composeMsg = OFTComposeMsgCodec.encode(
                _origin.nonce,
                _origin.srcEid,
                amountReceivedLD,
                _message.composeMsg()
            );

            // @dev Stores the lzCompose payload that will be executed in a separate tx.
            // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.
            // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.
            // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.
            // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.
            endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);
        }

        emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);
    }

    /**
     * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The LayerZero message.
     * @param _executor The address of the off-chain executor.
     * @param _extraData Arbitrary data passed by the msg executor.
     *
     * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
     * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
     */
    function _lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual override {
        _lzReceive(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Check if the peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint ID to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     *
     * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.
     */
    function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {
        return peers[_eid] == _peer;
    }

    /**
     * @dev Internal function to remove dust from the given local decimal amount.
     * @param _amountLD The amount in local decimals.
     * @return amountLD The amount after removing dust.
     *
     * @dev Prevents the loss of dust when moving amounts between chains with different decimals.
     * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).
     */
    function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {
        return (_amountLD / decimalConversionRate) * decimalConversionRate;
    }

    /**
     * @dev Internal function to convert an amount from shared decimals into local decimals.
     * @param _amountSD The amount in shared decimals.
     * @return amountLD The amount in local decimals.
     */
    function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {
        return _amountSD * decimalConversionRate;
    }

    /**
     * @dev Internal function to convert an amount from local decimals into shared decimals.
     * @param _amountLD The amount in local decimals.
     * @return amountSD The amount in shared decimals.
     */
    function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
        return uint64(_amountLD / decimalConversionRate);
    }

    /**
     * @dev Internal function to mock the amount mutation from a OFT debit() operation.
     * @param _amountLD The amount to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @dev _dstEid The destination endpoint ID.
     * @return amountSentLD The amount sent, in local decimals.
     * @return amountReceivedLD The amount to be received on the remote chain, in local decimals.
     *
     * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.
     */
    function _debitView(
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 /*_dstEid*/
    ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
        // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.
        amountSentLD = _removeDust(_amountLD);
        // @dev The amount to send is the same as amount received in the default implementation.
        amountReceivedLD = amountSentLD;

        // @dev Check for slippage.
        if (amountReceivedLD < _minAmountLD) {
            revert SlippageExceeded(amountReceivedLD, _minAmountLD);
        }
    }

    /**
     * @dev Internal function to perform a debit operation.
     * @param _from The address to debit.
     * @param _amountLD The amount to send in local decimals.
     * @param _minAmountLD The minimum amount to send in local decimals.
     * @param _dstEid The destination endpoint ID.
     * @return amountSentLD The amount sent in local decimals.
     * @return amountReceivedLD The amount received in local decimals on the remote.
     *
     * @dev Defined here but are intended to be overriden depending on the OFT implementation.
     * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
     */
    function _debit(
        address _from,
        uint256 _amountLD,
        uint256 _minAmountLD,
        uint32 _dstEid
    ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);

    /**
     * @dev Internal function to perform a credit operation.
     * @param _to The address to credit.
     * @param _amountLD The amount to credit in local decimals.
     * @param _srcEid The source endpoint ID.
     * @return amountReceivedLD The amount ACTUALLY received in local decimals.
     *
     * @dev Defined here but are intended to be overriden depending on the OFT implementation.
     * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
     */
    function _credit(
        address _to,
        uint256 _amountLD,
        uint32 _srcEid
    ) internal virtual returns (uint256 amountReceivedLD);
}

File 8 of 40 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

File 9 of 40 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 10 of 40 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 11 of 40 : OApp.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";

/**
 * @title OApp
 * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
 */
abstract contract OApp is OAppSender, OAppReceiver {
    /**
     * @dev Constructor to initialize the OApp with the provided endpoint and owner.
     * @param _endpoint The address of the LOCAL LayerZero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     */
    constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol implementation.
     * @return receiverVersion The version of the OAppReceiver.sol implementation.
     */
    function oAppVersion()
        public
        pure
        virtual
        override(OAppSender, OAppReceiver)
        returns (uint64 senderVersion, uint64 receiverVersion)
    {
        return (SENDER_VERSION, RECEIVER_VERSION);
    }
}

File 12 of 40 : OAppOptionsType3.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol";

/**
 * @title OAppOptionsType3
 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
 */
abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
    uint16 internal constant OPTION_TYPE_3 = 3;

    // @dev The "msgType" should be defined in the child contract.
    mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;

    /**
     * @dev Sets the enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
     * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
     * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
     * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
     */
    function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
        _setEnforcedOptions(_enforcedOptions);
    }

    /**
     * @dev Sets the enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     *
     * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
     * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
     * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
     * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
     */
    function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
        for (uint256 i = 0; i < _enforcedOptions.length; i++) {
            // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
            _assertOptionsType3(_enforcedOptions[i].options);
            enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
        }

        emit EnforcedOptionSet(_enforcedOptions);
    }

    /**
     * @notice Combines options for a given endpoint and message type.
     * @param _eid The endpoint ID.
     * @param _msgType The OAPP message type.
     * @param _extraOptions Additional options passed by the caller.
     * @return options The combination of caller specified options AND enforced options.
     *
     * @dev If there is an enforced lzReceive option:
     * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
     * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
     * @dev This presence of duplicated options is handled off-chain in the verifier/executor.
     */
    function combineOptions(
        uint32 _eid,
        uint16 _msgType,
        bytes calldata _extraOptions
    ) public view virtual returns (bytes memory) {
        bytes memory enforced = enforcedOptions[_eid][_msgType];

        // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
        if (enforced.length == 0) return _extraOptions;

        // No caller options, return enforced
        if (_extraOptions.length == 0) return enforced;

        // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
        if (_extraOptions.length >= 2) {
            _assertOptionsType3(_extraOptions);
            // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
            return bytes.concat(enforced, _extraOptions[2:]);
        }

        // No valid set of options was found.
        revert InvalidOptions(_extraOptions);
    }

    /**
     * @dev Internal function to assert that options are of type 3.
     * @param _options The options to be checked.
     */
    function _assertOptionsType3(bytes memory _options) internal pure virtual {
        uint16 optionsType;
        assembly {
            optionsType := mload(add(_options, 2))
        }
        if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
    }
}

File 13 of 40 : IOAppMsgInspector.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @title IOAppMsgInspector
 * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.
 */
interface IOAppMsgInspector {
    // Custom error message for inspection failure
    error InspectionFailed(bytes message, bytes options);

    /**
     * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.
     * @param _message The message payload to be inspected.
     * @param _options Additional options or parameters for inspection.
     * @return valid A boolean indicating whether the inspection passed (true) or failed (false).
     *
     * @dev Optionally done as a revert, OR use the boolean provided to handle the failure.
     */
    function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);
}

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

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IPreCrime } from "./interfaces/IPreCrime.sol";
import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol";

/**
 * @title OAppPreCrimeSimulator
 * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
 */
abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
    // The address of the preCrime implementation.
    address public preCrime;

    /**
     * @dev Retrieves the address of the OApp contract.
     * @return The address of the OApp contract.
     *
     * @dev The simulator contract is the base contract for the OApp by default.
     * @dev If the simulator is a separate contract, override this function.
     */
    function oApp() external view virtual returns (address) {
        return address(this);
    }

    /**
     * @dev Sets the preCrime contract address.
     * @param _preCrime The address of the preCrime contract.
     */
    function setPreCrime(address _preCrime) public virtual onlyOwner {
        preCrime = _preCrime;
        emit PreCrimeSet(_preCrime);
    }

    /**
     * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
     * @param _packets An array of InboundPacket objects representing received packets to be delivered.
     *
     * @dev WARNING: MUST revert at the end with the simulation results.
     * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
     * WITHOUT actually executing them.
     */
    function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
        for (uint256 i = 0; i < _packets.length; i++) {
            InboundPacket calldata packet = _packets[i];

            // Ignore packets that are not from trusted peers.
            if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;

            // @dev Because a verifier is calling this function, it doesnt have access to executor params:
            //  - address _executor
            //  - bytes calldata _extraData
            // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
            // They are instead stubbed to default values, address(0) and bytes("")
            // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
            // which would cause the revert to be ignored.
            this.lzReceiveSimulate{ value: packet.value }(
                packet.origin,
                packet.guid,
                packet.message,
                packet.executor,
                packet.extraData
            );
        }

        // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
        revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
    }

    /**
     * @dev Is effectively an internal function because msg.sender must be address(this).
     * Allows resetting the call stack for 'internal' calls.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _guid The unique identifier of the packet.
     * @param _message The message payload of the packet.
     * @param _executor The executor address for the packet.
     * @param _extraData Additional data for the packet.
     */
    function lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) external payable virtual {
        // @dev Ensure ONLY can be called 'internally'.
        if (msg.sender != address(this)) revert OnlySelf();
        _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
     * @param _origin The origin information.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address from the src chain.
     *  - nonce: The nonce of the LayerZero message.
     * @param _guid The GUID of the LayerZero message.
     * @param _message The LayerZero message.
     * @param _executor The address of the off-chain executor.
     * @param _extraData Arbitrary data passed by the msg executor.
     *
     * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
     * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
     */
    function _lzReceiveSimulate(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual;

    /**
     * @dev checks if the specified peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint Id to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     */
    function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
}

File 15 of 40 : IOFT.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { MessagingReceipt, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";

/**
 * @dev Struct representing token parameters for the OFT send() operation.
 */
struct SendParam {
    uint32 dstEid; // Destination endpoint ID.
    bytes32 to; // Recipient address.
    uint256 amountLD; // Amount to send in local decimals.
    uint256 minAmountLD; // Minimum amount to send in local decimals.
    bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
    bytes composeMsg; // The composed message for the send() operation.
    bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}

/**
 * @dev Struct representing OFT limit information.
 * @dev These amounts can change dynamically and are up the specific oft implementation.
 */
struct OFTLimit {
    uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
    uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}

/**
 * @dev Struct representing OFT receipt information.
 */
struct OFTReceipt {
    uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
    // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
    uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}

/**
 * @dev Struct representing OFT fee details.
 * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
 */
struct OFTFeeDetail {
    int256 feeAmountLD; // Amount of the fee in local decimals.
    string description; // Description of the fee.
}

/**
 * @title IOFT
 * @dev Interface for the OftChain (OFT) token.
 * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
 * @dev This specific interface ID is '0x02e49c2c'.
 */
interface IOFT {
    // Custom error messages
    error InvalidLocalDecimals();
    error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);

    // Events
    event OFTSent(
        bytes32 indexed guid, // GUID of the OFT message.
        uint32 dstEid, // Destination Endpoint ID.
        address indexed fromAddress, // Address of the sender on the src chain.
        uint256 amountSentLD, // Amount of tokens sent in local decimals.
        uint256 amountReceivedLD // Amount of tokens received in local decimals.
    );
    event OFTReceived(
        bytes32 indexed guid, // GUID of the OFT message.
        uint32 srcEid, // Source Endpoint ID.
        address indexed toAddress, // Address of the recipient on the dst chain.
        uint256 amountReceivedLD // Amount of tokens received in local decimals.
    );

    /**
     * @notice Retrieves interfaceID and the version of the OFT.
     * @return interfaceId The interface ID.
     * @return version The version.
     *
     * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
     * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
     * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
     * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
     */
    function oftVersion() external view returns (bytes4 interfaceId, uint64 version);

    /**
     * @notice Retrieves the address of the token associated with the OFT.
     * @return token The address of the ERC20 token implementation.
     */
    function token() external view returns (address);

    /**
     * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
     * @return requiresApproval Needs approval of the underlying token implementation.
     *
     * @dev Allows things like wallet implementers to determine integration requirements,
     * without understanding the underlying token implementation.
     */
    function approvalRequired() external view returns (bool);

    /**
     * @notice Retrieves the shared decimals of the OFT.
     * @return sharedDecimals The shared decimals of the OFT.
     */
    function sharedDecimals() external view returns (uint8);

    /**
     * @notice Provides a quote for OFT-related operations.
     * @param _sendParam The parameters for the send operation.
     * @return limit The OFT limit information.
     * @return oftFeeDetails The details of OFT fees.
     * @return receipt The OFT receipt information.
     */
    function quoteOFT(
        SendParam calldata _sendParam
    ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);

    /**
     * @notice Provides a quote for the send() operation.
     * @param _sendParam The parameters for the send() operation.
     * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
     * @return fee The calculated LayerZero messaging fee from the send() operation.
     *
     * @dev MessagingFee: LayerZero msg fee
     *  - nativeFee: The native fee.
     *  - lzTokenFee: The lzToken fee.
     */
    function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);

    /**
     * @notice Executes the send() operation.
     * @param _sendParam The parameters for the send operation.
     * @param _fee The fee information supplied by the caller.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess funds from fees etc. on the src.
     * @return receipt The LayerZero messaging receipt from the send() operation.
     * @return oftReceipt The OFT receipt information.
     *
     * @dev MessagingReceipt: LayerZero msg receipt
     *  - guid: The unique identifier for the sent message.
     *  - nonce: The nonce of the sent message.
     *  - fee: The LayerZero fee incurred for the message.
     */
    function send(
        SendParam calldata _sendParam,
        MessagingFee calldata _fee,
        address _refundAddress
    ) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}

File 16 of 40 : OFTMsgCodec.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

library OFTMsgCodec {
    // Offset constants for encoding and decoding OFT messages
    uint8 private constant SEND_TO_OFFSET = 32;
    uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;

    /**
     * @dev Encodes an OFT LayerZero message.
     * @param _sendTo The recipient address.
     * @param _amountShared The amount in shared decimals.
     * @param _composeMsg The composed message.
     * @return _msg The encoded message.
     * @return hasCompose A boolean indicating whether the message has a composed payload.
     */
    function encode(
        bytes32 _sendTo,
        uint64 _amountShared,
        bytes memory _composeMsg
    ) internal view returns (bytes memory _msg, bool hasCompose) {
        hasCompose = _composeMsg.length > 0;
        // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
        _msg = hasCompose
            ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
            : abi.encodePacked(_sendTo, _amountShared);
    }

    /**
     * @dev Checks if the OFT message is composed.
     * @param _msg The OFT message.
     * @return A boolean indicating whether the message is composed.
     */
    function isComposed(bytes calldata _msg) internal pure returns (bool) {
        return _msg.length > SEND_AMOUNT_SD_OFFSET;
    }

    /**
     * @dev Retrieves the recipient address from the OFT message.
     * @param _msg The OFT message.
     * @return The recipient address.
     */
    function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
        return bytes32(_msg[:SEND_TO_OFFSET]);
    }

    /**
     * @dev Retrieves the amount in shared decimals from the OFT message.
     * @param _msg The OFT message.
     * @return The amount in shared decimals.
     */
    function amountSD(bytes calldata _msg) internal pure returns (uint64) {
        return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
    }

    /**
     * @dev Retrieves the composed message from the OFT message.
     * @param _msg The OFT message.
     * @return The composed message.
     */
    function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
        return _msg[SEND_AMOUNT_SD_OFFSET:];
    }

    /**
     * @dev Converts an address to bytes32.
     * @param _addr The address to convert.
     * @return The bytes32 representation of the address.
     */
    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @dev Converts bytes32 to an address.
     * @param _b The bytes32 value to convert.
     * @return The address representation of bytes32.
     */
    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}

File 17 of 40 : OFTComposeMsgCodec.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

library OFTComposeMsgCodec {
    // Offset constants for decoding composed messages
    uint8 private constant NONCE_OFFSET = 8;
    uint8 private constant SRC_EID_OFFSET = 12;
    uint8 private constant AMOUNT_LD_OFFSET = 44;
    uint8 private constant COMPOSE_FROM_OFFSET = 76;

    /**
     * @dev Encodes a OFT composed message.
     * @param _nonce The nonce value.
     * @param _srcEid The source endpoint ID.
     * @param _amountLD The amount in local decimals.
     * @param _composeMsg The composed message.
     * @return _msg The encoded Composed message.
     */
    function encode(
        uint64 _nonce,
        uint32 _srcEid,
        uint256 _amountLD,
        bytes memory _composeMsg // 0x[composeFrom][composeMsg]
    ) internal pure returns (bytes memory _msg) {
        _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
    }

    /**
     * @dev Retrieves the nonce for the composed message.
     * @param _msg The message.
     * @return The nonce value.
     */
    function nonce(bytes calldata _msg) internal pure returns (uint64) {
        return uint64(bytes8(_msg[:NONCE_OFFSET]));
    }

    /**
     * @dev Retrieves the source endpoint ID for the composed message.
     * @param _msg The message.
     * @return The source endpoint ID.
     */
    function srcEid(bytes calldata _msg) internal pure returns (uint32) {
        return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    /**
     * @dev Retrieves the amount in local decimals from the composed message.
     * @param _msg The message.
     * @return The amount in local decimals.
     */
    function amountLD(bytes calldata _msg) internal pure returns (uint256) {
        return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
    }

    /**
     * @dev Retrieves the composeFrom value from the composed message.
     * @param _msg The message.
     * @return The composeFrom value.
     */
    function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
        return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
    }

    /**
     * @dev Retrieves the composed message.
     * @param _msg The message.
     * @return The composed message.
     */
    function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
        return _msg[COMPOSE_FROM_OFFSET:];
    }

    /**
     * @dev Converts an address to bytes32.
     * @param _addr The address to convert.
     * @return The bytes32 representation of the address.
     */
    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @dev Converts bytes32 to an address.
     * @param _b The bytes32 value to convert.
     * @return The address representation of bytes32.
     */
    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}

File 18 of 40 : OAppSender.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";

/**
 * @title OAppSender
 * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
 */
abstract contract OAppSender is OAppCore {
    using SafeERC20 for IERC20;

    // Custom error messages
    error NotEnoughNative(uint256 msgValue);
    error LzTokenUnavailable();

    // @dev The version of the OAppSender implementation.
    // @dev Version is bumped when changes are made to this contract.
    uint64 internal constant SENDER_VERSION = 1;

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     *
     * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
     * ie. this is a SEND only OApp.
     * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
     */
    function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
        return (SENDER_VERSION, 0);
    }

    /**
     * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
     * @param _dstEid The destination endpoint ID.
     * @param _message The message payload.
     * @param _options Additional options for the message.
     * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
     * @return fee The calculated MessagingFee for the message.
     *      - nativeFee: The native fee for the message.
     *      - lzTokenFee: The LZ token fee for the message.
     */
    function _quote(
        uint32 _dstEid,
        bytes memory _message,
        bytes memory _options,
        bool _payInLzToken
    ) internal view virtual returns (MessagingFee memory fee) {
        return
            endpoint.quote(
                MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
                address(this)
            );
    }

    /**
     * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
     * @param _dstEid The destination endpoint ID.
     * @param _message The message payload.
     * @param _options Additional options for the message.
     * @param _fee The calculated LayerZero fee for the message.
     *      - nativeFee: The native fee.
     *      - lzTokenFee: The lzToken fee.
     * @param _refundAddress The address to receive any excess fee values sent to the endpoint.
     * @return receipt The receipt for the sent message.
     *      - guid: The unique identifier for the sent message.
     *      - nonce: The nonce of the sent message.
     *      - fee: The LayerZero fee incurred for the message.
     */
    function _lzSend(
        uint32 _dstEid,
        bytes memory _message,
        bytes memory _options,
        MessagingFee memory _fee,
        address _refundAddress
    ) internal virtual returns (MessagingReceipt memory receipt) {
        // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
        uint256 messageValue = _payNative(_fee.nativeFee);
        if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);

        return
            // solhint-disable-next-line check-send-result
            endpoint.send{ value: messageValue }(
                MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
                _refundAddress
            );
    }

    /**
     * @dev Internal function to pay the native fee associated with the message.
     * @param _nativeFee The native fee to be paid.
     * @return nativeFee The amount of native currency paid.
     *
     * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
     * this will need to be overridden because msg.value would contain multiple lzFees.
     * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
     * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
     * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
     */
    function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
        if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
        return _nativeFee;
    }

    /**
     * @dev Internal function to pay the LZ token fee associated with the message.
     * @param _lzTokenFee The LZ token fee to be paid.
     *
     * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
     * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
     */
    function _payLzToken(uint256 _lzTokenFee) internal virtual {
        // @dev Cannot cache the token because it is not immutable in the endpoint.
        address lzToken = endpoint.lzToken();
        if (lzToken == address(0)) revert LzTokenUnavailable();

        // Pay LZ token fee by sending tokens to the endpoint.
        IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
    }
}

File 19 of 40 : OAppReceiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";

/**
 * @title OAppReceiver
 * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
 */
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
    // Custom error message for when the caller is not the registered endpoint/
    error OnlyEndpoint(address addr);

    // @dev The version of the OAppReceiver implementation.
    // @dev Version is bumped when changes are made to this contract.
    uint64 internal constant RECEIVER_VERSION = 2;

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     *
     * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
     * ie. this is a RECEIVE only OApp.
     * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
     */
    function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
        return (0, RECEIVER_VERSION);
    }

    /**
     * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
     * @dev _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @dev _message The lzReceive payload.
     * @param _sender The sender address.
     * @return isSender Is a valid sender.
     *
     * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
     * @dev The default sender IS the OAppReceiver implementer.
     */
    function isComposeMsgSender(
        Origin calldata /*_origin*/,
        bytes calldata /*_message*/,
        address _sender
    ) public view virtual returns (bool) {
        return _sender == address(this);
    }

    /**
     * @notice Checks if the path initialization is allowed based on the provided origin.
     * @param origin The origin information containing the source endpoint and sender address.
     * @return Whether the path has been initialized.
     *
     * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
     * @dev This defaults to assuming if a peer has been set, its initialized.
     * Can be overridden by the OApp if there is other logic to determine this.
     */
    function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
        return peers[origin.srcEid] == origin.sender;
    }

    /**
     * @notice Retrieves the next nonce for a given source endpoint and sender address.
     * @dev _srcEid The source endpoint ID.
     * @dev _sender The sender address.
     * @return nonce The next nonce.
     *
     * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
     * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
     * @dev This is also enforced by the OApp.
     * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
     */
    function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
        return 0;
    }

    /**
     * @dev Entry point for receiving messages or packets from the endpoint.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _guid The unique identifier for the received LayerZero message.
     * @param _message The payload of the received message.
     * @param _executor The address of the executor for the received message.
     * @param _extraData Additional arbitrary data provided by the corresponding executor.
     *
     * @dev Entry point for receiving msg/packet from the LayerZero endpoint.
     */
    function lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) public payable virtual {
        // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
        if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);

        // Ensure that the sender matches the expected peer for the source endpoint.
        if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);

        // Call the internal OApp implementation of lzReceive.
        _lzReceive(_origin, _guid, _message, _executor, _extraData);
    }

    /**
     * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
     */
    function _lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) internal virtual;
}

File 20 of 40 : OAppCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";

/**
 * @title OAppCore
 * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
 */
abstract contract OAppCore is IOAppCore, Ownable {
    // The LayerZero endpoint associated with the given OApp
    ILayerZeroEndpointV2 public immutable endpoint;

    // Mapping to store peers associated with corresponding endpoints
    mapping(uint32 eid => bytes32 peer) public peers;

    /**
     * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
     * @param _endpoint The address of the LOCAL Layer Zero endpoint.
     * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
     *
     * @dev The delegate typically should be set as the owner of the contract.
     */
    constructor(address _endpoint, address _delegate) {
        endpoint = ILayerZeroEndpointV2(_endpoint);

        if (_delegate == address(0)) revert InvalidDelegate();
        endpoint.setDelegate(_delegate);
    }

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
     * @dev Set this to bytes32(0) to remove the peer address.
     * @dev Peer is a bytes32 to accommodate non-evm chains.
     */
    function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
        _setPeer(_eid, _peer);
    }

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     *
     * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
     * @dev Set this to bytes32(0) to remove the peer address.
     * @dev Peer is a bytes32 to accommodate non-evm chains.
     */
    function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
        peers[_eid] = _peer;
        emit PeerSet(_eid, _peer);
    }

    /**
     * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
     * ie. the peer is set to bytes32(0).
     * @param _eid The endpoint ID.
     * @return peer The address of the peer associated with the specified endpoint.
     */
    function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
        bytes32 peer = peers[_eid];
        if (peer == bytes32(0)) revert NoPeer(_eid);
        return peer;
    }

    /**
     * @notice Sets the delegate address for the OApp.
     * @param _delegate The address of the delegate to be set.
     *
     * @dev Only the owner/admin of the OApp can call this function.
     * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
     */
    function setDelegate(address _delegate) public onlyOwner {
        endpoint.setDelegate(_delegate);
    }
}

File 21 of 40 : IOAppOptionsType3.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Struct representing enforced option parameters.
 */
struct EnforcedOptionParam {
    uint32 eid; // Endpoint ID
    uint16 msgType; // Message Type
    bytes options; // Additional options
}

/**
 * @title IOAppOptionsType3
 * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
 */
interface IOAppOptionsType3 {
    // Custom error message for invalid options
    error InvalidOptions(bytes options);

    // Event emitted when enforced options are set
    event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);

    /**
     * @notice Sets enforced options for specific endpoint and message type combinations.
     * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
     */
    function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;

    /**
     * @notice Combines options for a given endpoint and message type.
     * @param _eid The endpoint ID.
     * @param _msgType The OApp message type.
     * @param _extraOptions Additional options passed by the caller.
     * @return options The combination of caller specified options AND enforced options.
     */
    function combineOptions(
        uint32 _eid,
        uint16 _msgType,
        bytes calldata _extraOptions
    ) external view returns (bytes memory options);
}

File 22 of 40 : IPreCrime.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;
struct PreCrimePeer {
    uint32 eid;
    bytes32 preCrime;
    bytes32 oApp;
}

// TODO not done yet
interface IPreCrime {
    error OnlyOffChain();

    // for simulate()
    error PacketOversize(uint256 max, uint256 actual);
    error PacketUnsorted();
    error SimulationFailed(bytes reason);

    // for preCrime()
    error SimulationResultNotFound(uint32 eid);
    error InvalidSimulationResult(uint32 eid, bytes reason);
    error CrimeFound(bytes crime);

    function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);

    function simulate(
        bytes[] calldata _packets,
        uint256[] calldata _packetMsgValues
    ) external payable returns (bytes memory);

    function buildSimulationResult() external view returns (bytes memory);

    function preCrime(
        bytes[] calldata _packets,
        uint256[] calldata _packetMsgValues,
        bytes[] calldata _simulations
    ) external;

    function version() external view returns (uint64 major, uint8 minor);
}

File 23 of 40 : IOAppPreCrimeSimulator.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
// solhint-disable-next-line no-unused-import
import { InboundPacket, Origin } from "../libs/Packet.sol";

/**
 * @title IOAppPreCrimeSimulator Interface
 * @dev Interface for the preCrime simulation functionality in an OApp.
 */
interface IOAppPreCrimeSimulator {
    // @dev simulation result used in PreCrime implementation
    error SimulationResult(bytes result);
    error OnlySelf();

    /**
     * @dev Emitted when the preCrime contract address is set.
     * @param preCrimeAddress The address of the preCrime contract.
     */
    event PreCrimeSet(address preCrimeAddress);

    /**
     * @dev Retrieves the address of the preCrime contract implementation.
     * @return The address of the preCrime contract.
     */
    function preCrime() external view returns (address);

    /**
     * @dev Retrieves the address of the OApp contract.
     * @return The address of the OApp contract.
     */
    function oApp() external view returns (address);

    /**
     * @dev Sets the preCrime contract address.
     * @param _preCrime The address of the preCrime contract.
     */
    function setPreCrime(address _preCrime) external;

    /**
     * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
     * @param _packets An array of LayerZero InboundPacket objects representing received packets.
     */
    function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;

    /**
     * @dev checks if the specified peer is considered 'trusted' by the OApp.
     * @param _eid The endpoint Id to check.
     * @param _peer The peer to check.
     * @return Whether the peer passed is considered 'trusted' by the OApp.
     */
    function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
}

File 24 of 40 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.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 An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, 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);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

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

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

    /**
     * @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);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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(token).code.length > 0;
    }
}

File 25 of 40 : ILayerZeroEndpointV2.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";

struct MessagingParams {
    uint32 dstEid;
    bytes32 receiver;
    bytes message;
    bytes options;
    bool payInLzToken;
}

struct MessagingReceipt {
    bytes32 guid;
    uint64 nonce;
    MessagingFee fee;
}

struct MessagingFee {
    uint256 nativeFee;
    uint256 lzTokenFee;
}

struct Origin {
    uint32 srcEid;
    bytes32 sender;
    uint64 nonce;
}

interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
    event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

    event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);

    event PacketDelivered(Origin origin, address receiver);

    event LzReceiveAlert(
        address indexed receiver,
        address indexed executor,
        Origin origin,
        bytes32 guid,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    event LzTokenSet(address token);

    event DelegateSet(address sender, address delegate);

    function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);

    function send(
        MessagingParams calldata _params,
        address _refundAddress
    ) external payable returns (MessagingReceipt memory);

    function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;

    function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);

    function initializable(Origin calldata _origin, address _receiver) external view returns (bool);

    function lzReceive(
        Origin calldata _origin,
        address _receiver,
        bytes32 _guid,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;

    // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
    function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;

    function setLzToken(address _lzToken) external;

    function lzToken() external view returns (address);

    function nativeToken() external view returns (address);

    function setDelegate(address _delegate) external;
}

File 26 of 40 : IOAppReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";

interface IOAppReceiver is ILayerZeroReceiver {
    /**
     * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
     * @param _origin The origin information containing the source endpoint and sender address.
     *  - srcEid: The source chain endpoint ID.
     *  - sender: The sender address on the src chain.
     *  - nonce: The nonce of the message.
     * @param _message The lzReceive payload.
     * @param _sender The sender address.
     * @return isSender Is a valid sender.
     *
     * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
     * @dev The default sender IS the OAppReceiver implementer.
     */
    function isComposeMsgSender(
        Origin calldata _origin,
        bytes calldata _message,
        address _sender
    ) external view returns (bool isSender);
}

File 27 of 40 : IOAppCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

/**
 * @title IOAppCore
 */
interface IOAppCore {
    // Custom error messages
    error OnlyPeer(uint32 eid, bytes32 sender);
    error NoPeer(uint32 eid);
    error InvalidEndpointCall();
    error InvalidDelegate();

    // Event emitted when a peer (OApp) is set for a corresponding endpoint
    event PeerSet(uint32 eid, bytes32 peer);

    /**
     * @notice Retrieves the OApp version information.
     * @return senderVersion The version of the OAppSender.sol contract.
     * @return receiverVersion The version of the OAppReceiver.sol contract.
     */
    function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);

    /**
     * @notice Retrieves the LayerZero endpoint associated with the OApp.
     * @return iEndpoint The LayerZero endpoint as an interface.
     */
    function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);

    /**
     * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @return peer The peer address (OApp instance) associated with the corresponding endpoint.
     */
    function peers(uint32 _eid) external view returns (bytes32 peer);

    /**
     * @notice Sets the peer address (OApp instance) for a corresponding endpoint.
     * @param _eid The endpoint ID.
     * @param _peer The address of the peer to be associated with the corresponding endpoint.
     */
    function setPeer(uint32 _eid, bytes32 _peer) external;

    /**
     * @notice Sets the delegate address for the OApp Core.
     * @param _delegate The address of the delegate to be set.
     */
    function setDelegate(address _delegate) external;
}

File 28 of 40 : Packet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";

/**
 * @title InboundPacket
 * @dev Structure representing an inbound packet received by the contract.
 */
struct InboundPacket {
    Origin origin; // Origin information of the packet.
    uint32 dstEid; // Destination endpointId of the packet.
    address receiver; // Receiver address for the packet.
    bytes32 guid; // Unique identifier of the packet.
    uint256 value; // msg.value of the packet.
    address executor; // Executor address for the packet.
    bytes message; // Message payload of the packet.
    bytes extraData; // Additional arbitrary data for the packet.
}

/**
 * @title PacketDecoder
 * @dev Library for decoding LayerZero packets.
 */
library PacketDecoder {
    using PacketV1Codec for bytes;

    /**
     * @dev Decode an inbound packet from the given packet data.
     * @param _packet The packet data to decode.
     * @return packet An InboundPacket struct representing the decoded packet.
     */
    function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
        packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
        packet.dstEid = _packet.dstEid();
        packet.receiver = _packet.receiverB20();
        packet.guid = _packet.guid();
        packet.message = _packet.message();
    }

    /**
     * @dev Decode multiple inbound packets from the given packet data and associated message values.
     * @param _packets An array of packet data to decode.
     * @param _packetMsgValues An array of associated message values for each packet.
     * @return packets An array of InboundPacket structs representing the decoded packets.
     */
    function decode(
        bytes[] calldata _packets,
        uint256[] memory _packetMsgValues
    ) internal pure returns (InboundPacket[] memory packets) {
        packets = new InboundPacket[](_packets.length);
        for (uint256 i = 0; i < _packets.length; i++) {
            bytes calldata packet = _packets[i];
            packets[i] = PacketDecoder.decode(packet);
            // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.
            packets[i].value = _packetMsgValues[i];
        }
    }
}

File 29 of 40 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @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.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
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].
     *
     * CAUTION: See Security Considerations above.
     */
    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);
}

File 30 of 40 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) 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 FailedInnerCall();
        }
    }
}

File 31 of 40 : IMessageLibManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

struct SetConfigParam {
    uint32 eid;
    uint32 configType;
    bytes config;
}

interface IMessageLibManager {
    struct Timeout {
        address lib;
        uint256 expiry;
    }

    event LibraryRegistered(address newLib);
    event DefaultSendLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibrarySet(uint32 eid, address newLib);
    event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
    event SendLibrarySet(address sender, uint32 eid, address newLib);
    event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
    event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);

    function registerLibrary(address _lib) external;

    function isRegisteredLibrary(address _lib) external view returns (bool);

    function getRegisteredLibraries() external view returns (address[] memory);

    function setDefaultSendLibrary(uint32 _eid, address _newLib) external;

    function defaultSendLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;

    function defaultReceiveLibrary(uint32 _eid) external view returns (address);

    function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;

    function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);

    /// ------------------- OApp interfaces -------------------
    function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;

    function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);

    function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);

    function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;

    function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);

    function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;

    function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);

    function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;

    function getConfig(
        address _oapp,
        address _lib,
        uint32 _eid,
        uint32 _configType
    ) external view returns (bytes memory config);
}

File 32 of 40 : IMessagingComposer.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingComposer {
    event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
    event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
    event LzComposeAlert(
        address indexed from,
        address indexed to,
        address indexed executor,
        bytes32 guid,
        uint16 index,
        uint256 gas,
        uint256 value,
        bytes message,
        bytes extraData,
        bytes reason
    );

    function composeQueue(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index
    ) external view returns (bytes32 messageHash);

    function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;

    function lzCompose(
        address _from,
        address _to,
        bytes32 _guid,
        uint16 _index,
        bytes calldata _message,
        bytes calldata _extraData
    ) external payable;
}

File 33 of 40 : IMessagingChannel.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingChannel {
    event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
    event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
    event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);

    function eid() external view returns (uint32);

    // this is an emergency function if a message cannot be verified for some reasons
    // required to provide _nextNonce to avoid race condition
    function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;

    function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;

    function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);

    function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);

    function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);

    function inboundPayloadHash(
        address _receiver,
        uint32 _srcEid,
        bytes32 _sender,
        uint64 _nonce
    ) external view returns (bytes32);

    function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}

File 34 of 40 : IMessagingContext.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

interface IMessagingContext {
    function isSendingMessage() external view returns (bool);

    function getSendContext() external view returns (uint32 dstEid, address sender);
}

File 35 of 40 : ILayerZeroReceiver.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { Origin } from "./ILayerZeroEndpointV2.sol";

interface ILayerZeroReceiver {
    function allowInitializePath(Origin calldata _origin) external view returns (bool);

    function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);

    function lzReceive(
        Origin calldata _origin,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) external payable;
}

File 36 of 40 : PacketV1Codec.sol
// SPDX-License-Identifier: LZBL-1.2

pragma solidity ^0.8.20;

import { Packet } from "../../interfaces/ISendLib.sol";
import { AddressCast } from "../../libs/AddressCast.sol";

library PacketV1Codec {
    using AddressCast for address;
    using AddressCast for bytes32;

    uint8 internal constant PACKET_VERSION = 1;

    // header (version + nonce + path)
    // version
    uint256 private constant PACKET_VERSION_OFFSET = 0;
    //    nonce
    uint256 private constant NONCE_OFFSET = 1;
    //    path
    uint256 private constant SRC_EID_OFFSET = 9;
    uint256 private constant SENDER_OFFSET = 13;
    uint256 private constant DST_EID_OFFSET = 45;
    uint256 private constant RECEIVER_OFFSET = 49;
    // payload (guid + message)
    uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
    uint256 private constant MESSAGE_OFFSET = 113;

    function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
        encodedPacket = abi.encodePacked(
            PACKET_VERSION,
            _packet.nonce,
            _packet.srcEid,
            _packet.sender.toBytes32(),
            _packet.dstEid,
            _packet.receiver,
            _packet.guid,
            _packet.message
        );
    }

    function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                PACKET_VERSION,
                _packet.nonce,
                _packet.srcEid,
                _packet.sender.toBytes32(),
                _packet.dstEid,
                _packet.receiver
            );
    }

    function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
        return abi.encodePacked(_packet.guid, _packet.message);
    }

    function header(bytes calldata _packet) internal pure returns (bytes calldata) {
        return _packet[0:GUID_OFFSET];
    }

    function version(bytes calldata _packet) internal pure returns (uint8) {
        return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
    }

    function nonce(bytes calldata _packet) internal pure returns (uint64) {
        return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    function srcEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
    }

    function sender(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
    }

    function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
        return sender(_packet).toAddress();
    }

    function dstEid(bytes calldata _packet) internal pure returns (uint32) {
        return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
    }

    function receiver(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
    }

    function receiverB20(bytes calldata _packet) internal pure returns (address) {
        return receiver(_packet).toAddress();
    }

    function guid(bytes calldata _packet) internal pure returns (bytes32) {
        return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
    }

    function message(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[MESSAGE_OFFSET:]);
    }

    function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
        return bytes(_packet[GUID_OFFSET:]);
    }

    function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
        return keccak256(payload(_packet));
    }
}

File 37 of 40 : ISendLib.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

import { MessagingFee } from "./ILayerZeroEndpointV2.sol";
import { IMessageLib } from "./IMessageLib.sol";

struct Packet {
    uint64 nonce;
    uint32 srcEid;
    address sender;
    uint32 dstEid;
    bytes32 receiver;
    bytes32 guid;
    bytes message;
}

interface ISendLib is IMessageLib {
    function send(
        Packet calldata _packet,
        bytes calldata _options,
        bool _payInLzToken
    ) external returns (MessagingFee memory, bytes memory encodedPacket);

    function quote(
        Packet calldata _packet,
        bytes calldata _options,
        bool _payInLzToken
    ) external view returns (MessagingFee memory);

    function setTreasury(address _treasury) external;

    function withdrawFee(address _to, uint256 _amount) external;

    function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
}

File 38 of 40 : AddressCast.sol
// SPDX-License-Identifier: LZBL-1.2

pragma solidity ^0.8.20;

library AddressCast {
    error AddressCast_InvalidSizeForAddress();
    error AddressCast_InvalidAddress();

    function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
        if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
        result = bytes32(_addressBytes);
        unchecked {
            uint256 offset = 32 - _addressBytes.length;
            result = result >> (offset * 8);
        }
    }

    function toBytes32(address _address) internal pure returns (bytes32 result) {
        result = bytes32(uint256(uint160(_address)));
    }

    function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
        if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
        result = new bytes(_size);
        unchecked {
            uint256 offset = 256 - _size * 8;
            assembly {
                mstore(add(result, 32), shl(offset, _addressBytes32))
            }
        }
    }

    function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
        result = address(uint160(uint256(_addressBytes32)));
    }

    function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
        if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
        result = address(bytes20(_addressBytes));
    }
}

File 39 of 40 : IMessageLib.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

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

import { SetConfigParam } from "./IMessageLibManager.sol";

enum MessageLibType {
    Send,
    Receive,
    SendAndReceive
}

interface IMessageLib is IERC165 {
    function setConfig(address _oapp, SetConfigParam[] calldata _config) external;

    function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);

    function isSupportedEid(uint32 _eid) external view returns (bool);

    // message libs of same major version are compatible
    function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);

    function messageLibType() external view returns (MessageLibType);
}

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

pragma solidity ^0.8.20;

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

Settings
{
  "remappings": [
    "@layerzerolabs/=node_modules/@layerzerolabs/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "forge-std/=lib/forge-std/src/",
    "solidity-bytes-utils/=node_modules/solidity-bytes-utils/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_delegate","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c060405234801561001057600080fd5b50604051613fba380380613fba83398101604081905261002f91610251565b6040518060400160405280601481526020017f46616e6b6f204f6666696369616c20546f6b656e000000000000000000000000815250604051806040016040528060038152602001623930bd60e91b815250838383836100936101db60201b60201c565b8484818181818d6001600160a01b0381166100c857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100d1816101e0565b506001600160a01b0380831660805281166100ff57604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b15801561014657600080fd5b505af115801561015a573d6000803e3d6000fd5b505050505050505061017061023060201b60201c565b60ff168360ff161015610196576040516301e9714b60e41b815260040160405180910390fd5b6101a160068461029a565b6101ac90600a6103a0565b60a05250600891506101c090508382610455565b5060096101cd8282610455565b505050505050505050610513565b601290565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600690565b80516001600160a01b038116811461024c57600080fd5b919050565b6000806040838503121561026457600080fd5b61026d83610235565b915061027b60208401610235565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b60ff82811682821603908111156102b3576102b3610284565b92915050565b6001815b60018411156102f4578085048111156102d8576102d8610284565b60018416156102e657908102905b60019390931c9280026102bd565b935093915050565b60008261030b575060016102b3565b81610318575060006102b3565b816001811461032e576002811461033857610354565b60019150506102b3565b60ff84111561034957610349610284565b50506001821b6102b3565b5060208310610133831016604e8410600b8410161715610377575081810a6102b3565b61038460001984846102b9565b806000190482111561039857610398610284565b029392505050565b60006103af60ff8416836102fc565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806103e057607f821691505b60208210810361040057634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561045057806000526020600020601f840160051c8101602085101561042d5750805b601f840160051c820191505b8181101561044d5760008155600101610439565b50505b505050565b81516001600160401b0381111561046e5761046e6103b6565b6104828161047c84546103cc565b84610406565b6020601f8211600181146104b6576000831561049e5750848201515b600019600385901b1c1916600184901b17845561044d565b600084815260208120601f198516915b828110156104e657878501518255602094850194600190920191016104c6565b50848210156105045786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60805160a051613a3c61057e600039600081816106ed01528181611f4d01528181611fc2015261225501526000818161059101528181610a7701528181611282015281816115bd01528181611a2a01528181611d1c015281816123ad01526124a60152613a3c6000f3fe6080604052600436106102d15760003560e01c80637d25a05e11610179578063bb0b6a53116100d6578063d045a0dc1161008a578063f2fde38b11610064578063f2fde38b146108b7578063fc0c546a14610515578063ff7bd03d146108d757600080fd5b8063d045a0dc14610831578063d424388514610844578063dd62ed3e1461086457600080fd5b8063bd815db0116100bb578063bd815db0146107dd578063c7c7f5b3146107f0578063ca5eb5e11461081157600080fd5b8063bb0b6a5314610790578063bc70b354146107bd57600080fd5b8063963efcaa1161012d578063a9059cbb11610112578063a9059cbb14610723578063b731ea0a14610743578063b98bd0701461077057600080fd5b8063963efcaa146106db5780639f68b9641461070f57600080fd5b8063857749b01161015e578063857749b0146106875780638da5cb5b1461069b57806395d89b41146106c657600080fd5b80637d25a05e1461062b57806382413eac1461066757600080fd5b806323b872dd116102325780635535d461116101e65780636fc1b31e116101c05780636fc1b31e146105b357806370a08231146105d3578063715018a61461061657600080fd5b80635535d461146105285780635a0dfe4d146105485780635e280f111461057f57600080fd5b80633400288b116102175780633400288b146104c85780633b6f743b146104e857806352ae28791461051557600080fd5b806323b872dd14610486578063313ce567146104a657600080fd5b8063134d4f251161028957806317442b701161026e57806317442b701461043057806318160ddd146104525780631f5e13341461047157600080fd5b8063134d4f25146103c7578063156a0d0f146103ef57600080fd5b80630d35b415116102ba5780630d35b41514610331578063111ecdad1461036057806313137d65146103b257600080fd5b806306fdde03146102d6578063095ea7b314610301575b600080fd5b3480156102e257600080fd5b506102eb6108f7565b6040516102f89190612843565b60405180910390f35b34801561030d57600080fd5b5061032161031c366004612878565b610989565b60405190151581526020016102f8565b34801561033d57600080fd5b5061035161034c3660046128bc565b6109a3565b6040516102f8939291906128f1565b34801561036c57600080fd5b5060045461038d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6103c56103c0366004612a07565b610a75565b005b3480156103d357600080fd5b506103dc600281565b60405161ffff90911681526020016102f8565b3480156103fb57600080fd5b50604080517f02e49c2c00000000000000000000000000000000000000000000000000000000815260016020820152016102f8565b34801561043c57600080fd5b50604080516001815260026020820152016102f8565b34801561045e57600080fd5b506007545b6040519081526020016102f8565b34801561047d57600080fd5b506103dc600181565b34801561049257600080fd5b506103216104a1366004612aaa565b610b74565b3480156104b257600080fd5b5060125b60405160ff90911681526020016102f8565b3480156104d457600080fd5b506103c56104e3366004612b04565b610b9a565b3480156104f457600080fd5b50610508610503366004612b2e565b610bb0565b6040516102f89190612b80565b34801561052157600080fd5b503061038d565b34801561053457600080fd5b506102eb610543366004612ba9565b610c17565b34801561055457600080fd5b50610321610563366004612b04565b63ffffffff919091166000908152600160205260409020541490565b34801561058b57600080fd5b5061038d7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105bf57600080fd5b506103c56105ce366004612bdc565b610cbc565b3480156105df57600080fd5b506104636105ee366004612bdc565b73ffffffffffffffffffffffffffffffffffffffff1660009081526005602052604090205490565b34801561062257600080fd5b506103c5610d3e565b34801561063757600080fd5b5061064e610646366004612b04565b600092915050565b60405167ffffffffffffffff90911681526020016102f8565b34801561067357600080fd5b50610321610682366004612bf9565b610d52565b34801561069357600080fd5b5060066104b6565b3480156106a757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661038d565b3480156106d257600080fd5b506102eb610d74565b3480156106e757600080fd5b506104637f000000000000000000000000000000000000000000000000000000000000000081565b34801561071b57600080fd5b506000610321565b34801561072f57600080fd5b5061032161073e366004612878565b610d83565b34801561074f57600080fd5b5060025461038d9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561077c57600080fd5b506103c561078b366004612ca5565b610d91565b34801561079c57600080fd5b506104636107ab366004612ce7565b60016020526000908152604090205481565b3480156107c957600080fd5b506102eb6107d8366004612d02565b610dab565b6103c56107eb366004612ca5565b610f6c565b6108036107fe366004612d63565b61113a565b6040516102f8929190612def565b34801561081d57600080fd5b506103c561082c366004612bdc565b611235565b6103c561083f366004612a07565b6112e1565b34801561085057600080fd5b506103c561085f366004612bdc565b611329565b34801561087057600080fd5b5061046361087f366004612e42565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260066020908152604080832093909416825291909152205490565b3480156108c357600080fd5b506103c56108d2366004612bdc565b6113a4565b3480156108e357600080fd5b506103216108f2366004612e70565b611408565b60606008805461090690612e8c565b80601f016020809104026020016040519081016040528092919081815260200182805461093290612e8c565b801561097f5780601f106109545761010080835404028352916020019161097f565b820191906000526020600020905b81548152906001019060200180831161096257829003601f168201915b5050505050905090565b60003361099781858561143e565b60019150505b92915050565b604080518082019091526000808252602082015260606109d6604051806040016040528060008152602001600081525090565b604080518082018252600080825267ffffffffffffffff602080840182905284518381529081019094529195509182610a32565b604080518082019091526000815260606020820152815260200190600190039081610a0a5790505b509350600080610a57604089013560608a0135610a5260208c018c612ce7565b611450565b60408051808201909152918252602082015296989597505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610aeb576040517f91ac5e4f0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60208701803590610b0590610b00908a612ce7565b6114ad565b14610b5c57610b176020880188612ce7565b6040517fc26bebcc00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260208801356024820152604401610ae2565b610b6b87878787878787611502565b50505050505050565b600033610b8285828561169c565b610b8d85858561176b565b60019150505b9392505050565b610ba2611816565b610bac8282611869565b5050565b60408051808201909152600080825260208201526000610be060408501356060860135610a526020880188612ce7565b915050600080610bf086846118be565b9092509050610c0d610c056020880188612ce7565b838388611a14565b9695505050505050565b600360209081526000928352604080842090915290825290208054610c3b90612e8c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6790612e8c565b8015610cb45780601f10610c8957610100808354040283529160200191610cb4565b820191906000526020600020905b815481529060010190602001808311610c9757829003601f168201915b505050505081565b610cc4611816565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610d46611816565b610d506000611b02565b565b73ffffffffffffffffffffffffffffffffffffffff811630145b949350505050565b60606009805461090690612e8c565b60003361099781858561176b565b610d99611816565b610bac610da68284612fe9565b611b77565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610ddf90612e8c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0b90612e8c565b8015610e585780601f10610e2d57610100808354040283529160200191610e58565b820191906000526020600020905b815481529060010190602001808311610e3b57829003601f168201915b505050505090508051600003610ea85783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610d6c9350505050565b6000839003610eb8579050610d6c565b60028310610f3657610eff84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c7e92505050565b80610f0d8460028188613115565b604051602001610f1f9392919061313f565b604051602081830303815290604052915050610d6c565b83836040517f9a6d49cd000000000000000000000000000000000000000000000000000000008152600401610ae29291906131b0565b60005b818110156110755736838383818110610f8a57610f8a6131c4565b9050602002810190610f9c91906131f3565b9050610fcf610fae6020830183612ce7565b602083013563ffffffff919091166000908152600160205260409020541490565b610fd9575061106d565b3063d045a0dc60c08301358360a0810135610ff8610100830183613231565b611009610100890160e08a01612bdc565b6110176101208a018a613231565b6040518963ffffffff1660e01b815260040161103997969594939291906132ac565b6000604051808303818588803b15801561105257600080fd5b505af1158015611066573d6000803e3d6000fd5b5050505050505b600101610f6f565b503373ffffffffffffffffffffffffffffffffffffffff16638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156110c1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111079190810190613340565b6040517f8351eea7000000000000000000000000000000000000000000000000000000008152600401610ae29190612843565b61114261278d565b604080518082019091526000808252602082015260008061117933604089013560608a013561117460208c018c612ce7565b611cc3565b9150915060008061118a89846118be565b90925090506111b661119f60208b018b612ce7565b83836111b0368d90038d018d6133ae565b8b611ce9565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611204908d018d612ce7565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b61123d611816565b6040517fca5eb5e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b1580156112c657600080fd5b505af11580156112da573d6000803e3d6000fd5b5050505050565b33301461131a576040517f14d4a4e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b6b87878787878787610b5c565b611331611816565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610d33565b6113ac611816565b73ffffffffffffffffffffffffffffffffffffffff81166113fc576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b61140581611b02565b50565b60006020820180359060019083906114209086612ce7565b63ffffffff1681526020810191909152604001600020541492915050565b61144b8383836001611e01565b505050565b60008061145c85611f49565b9150819050838110156114a5576040517f71c4efed0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610ae2565b935093915050565b63ffffffff81166000908152600160205260408120548061099d576040517ff6ff4fb700000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152602401610ae2565b60006115146115118787611f80565b90565b905060006115408261152e6115298a8a611f98565b611fbb565b61153b60208d018d612ce7565b611ff1565b9050602886111561162d57600061157d61156060608c0160408d016133e1565b61156d60208d018d612ce7565b846115788c8c612026565b612071565b6040517f7cb5901200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906115f99086908d9060009087906004016133fe565b600060405180830381600087803b15801561161357600080fd5b505af1158015611627573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff8216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61167360208d018d612ce7565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600660209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146117655781811015611756576040517ffb8f41b200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810182905260448101839052606401610ae2565b61176584848484036000611e01565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166117bb576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff821661180b576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b61144b8383836120a3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d50576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ae2565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061191b85602001356118d48661224e565b6118e160a0890189613231565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061227a92505050565b909350905060008161192e576001611931565b60025b90506119516119436020880188612ce7565b826107d860808a018a613231565b60045490935073ffffffffffffffffffffffffffffffffffffffff168015611a0a576040517f043a78eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063043a78eb906119c7908890889060040161343d565b602060405180830381865afa1580156119e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a089190613462565b505b5050509250929050565b60408051808201909152600080825260208201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ddc28c586040518060a001604052808863ffffffff168152602001611a84896114ad565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611ab992919061347f565b6040805180830381865afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190613554565b95945050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c4e57611ba9828281518110611b9857611b986131c4565b602002602001015160400151611c7e565b818181518110611bbb57611bbb6131c4565b60200260200101516040015160036000848481518110611bdd57611bdd6131c4565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c1757611c176131c4565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c4591906135b7565b50600101611b7a565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610d3391906136d0565b600281015161ffff8116600314610bac57816040517f9a6d49cd000000000000000000000000000000000000000000000000000000008152600401610ae29190612843565b600080611cd1858585611450565b9092509050611ce0868361230c565b94509492505050565b611cf161278d565b6000611d008460000151612368565b602085015190915015611d1a57611d1a84602001516123a9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632637a450826040518060a001604052808b63ffffffff168152602001611d778c6114ad565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611db392919061347f565b60806040518083038185885af1158015611dd1573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611df6919061377e565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416611e51576040517fe602df0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff8316611ea1576040517f94280d6200000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526006602090815260408083209387168352929052208290558015611765578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611f3b91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000611f7681846137f9565b61099d9190613834565b6000611f8f6020828486613115565b610b939161384b565b6000611fa8602860208486613115565b611fb191613887565b60c01c9392505050565b600061099d7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8416613834565b600073ffffffffffffffffffffffffffffffffffffffff84166120145761dead93505b61201e84846124cb565b509092915050565b60606120358260288186613115565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161208a94939291906138ed565b6040516020818303038152906040529050949350505050565b73ffffffffffffffffffffffffffffffffffffffff83166120db5780600760008282546120d0919061396b565b9091555061218d9050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602052604090205481811015612161576040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024810182905260448101839052606401610ae2565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602052604090209082900390555b73ffffffffffffffffffffffffffffffffffffffff82166121b6576007805482900390556121e2565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090208054820190555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161224191815260200190565b60405180910390a3505050565b600061099d7f0000000000000000000000000000000000000000000000000000000000000000836137f9565b80516060901515806122db5784846040516020016122c792919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b604051602081830303815290604052612302565b848433856040516020016122f2949392919061397e565b6040516020818303038152906040525b9150935093915050565b73ffffffffffffffffffffffffffffffffffffffff821661235c576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b610bac826000836120a3565b60008134146123a5576040517f9f704120000000000000000000000000000000000000000000000000000000008152346004820152602401610ae2565b5090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a91906139d7565b905073ffffffffffffffffffffffffffffffffffffffff8116612489576040517f5373352a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bac73ffffffffffffffffffffffffffffffffffffffff8216337f000000000000000000000000000000000000000000000000000000000000000085612527565b73ffffffffffffffffffffffffffffffffffffffff821661251b576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b610bac600083836120a3565b6040805173ffffffffffffffffffffffffffffffffffffffff8581166024830152848116604483015260648083018590528351808403909101815260849092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611765918691906000906125c89084168361263c565b905080516000141580156125ed5750808060200190518101906125eb9190613462565b155b1561144b576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610ae2565b6060610b9383836000846000808573ffffffffffffffffffffffffffffffffffffffff16848660405161266f91906139f4565b60006040518083038185875af1925050503d80600081146126ac576040519150601f19603f3d011682016040523d82523d6000602084013e6126b1565b606091505b5091509150610c0d8683836060826126d1576126cc8261274b565b610b93565b81511580156126f5575073ffffffffffffffffffffffffffffffffffffffff84163b155b15612744576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610ae2565b5080610b93565b80511561275b5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806060016040528060008019168152602001600067ffffffffffffffff1681526020016127d0604051806040016040528060008152602001600081525090565b905290565b60005b838110156127f05781810151838201526020016127d8565b50506000910152565b600081518084526128118160208601602086016127d5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b9360208301846127f9565b73ffffffffffffffffffffffffffffffffffffffff8116811461140557600080fd5b6000806040838503121561288b57600080fd5b823561289681612856565b946020939093013593505050565b600060e082840312156128b657600080fd5b50919050565b6000602082840312156128ce57600080fd5b813567ffffffffffffffff8111156128e557600080fd5b610d6c848285016128a4565b8351815260208085015190820152600060a0820160a0604084015280855180835260c08501915060c08160051b86010192506020870160005b82811015612990577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40878603018452815180518652602081015190506040602087015261297a60408701826127f9565b955050602093840193919091019060010161292a565b5050855160608601525050602084015160808401529050610d6c565b6000606082840312156128b657600080fd5b60008083601f8401126129d057600080fd5b50813567ffffffffffffffff8111156129e857600080fd5b602083019150836020828501011115612a0057600080fd5b9250929050565b600080600080600080600060e0888a031215612a2257600080fd5b612a2c89896129ac565b965060608801359550608088013567ffffffffffffffff811115612a4f57600080fd5b612a5b8a828b016129be565b90965094505060a0880135612a6f81612856565b925060c088013567ffffffffffffffff811115612a8b57600080fd5b612a978a828b016129be565b989b979a50959850939692959293505050565b600080600060608486031215612abf57600080fd5b8335612aca81612856565b92506020840135612ada81612856565b929592945050506040919091013590565b803563ffffffff81168114612aff57600080fd5b919050565b60008060408385031215612b1757600080fd5b61289683612aeb565b801515811461140557600080fd5b60008060408385031215612b4157600080fd5b823567ffffffffffffffff811115612b5857600080fd5b612b64858286016128a4565b9250506020830135612b7581612b20565b809150509250929050565b81518152602080830151908201526040810161099d565b803561ffff81168114612aff57600080fd5b60008060408385031215612bbc57600080fd5b612bc583612aeb565b9150612bd360208401612b97565b90509250929050565b600060208284031215612bee57600080fd5b8135610b9381612856565b60008060008060a08587031215612c0f57600080fd5b612c1986866129ac565b9350606085013567ffffffffffffffff811115612c3557600080fd5b612c41878288016129be565b9094509250506080850135612c5581612856565b939692955090935050565b60008083601f840112612c7257600080fd5b50813567ffffffffffffffff811115612c8a57600080fd5b6020830191508360208260051b8501011115612a0057600080fd5b60008060208385031215612cb857600080fd5b823567ffffffffffffffff811115612ccf57600080fd5b612cdb85828601612c60565b90969095509350505050565b600060208284031215612cf957600080fd5b610b9382612aeb565b60008060008060608587031215612d1857600080fd5b612d2185612aeb565b9350612d2f60208601612b97565b9250604085013567ffffffffffffffff811115612d4b57600080fd5b612d57878288016129be565b95989497509550505050565b60008060008385036080811215612d7957600080fd5b843567ffffffffffffffff811115612d9057600080fd5b612d9c878288016128a4565b94505060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082011215612dcf57600080fd5b506020840191506060840135612de481612856565b809150509250925092565b600060c0820190508351825267ffffffffffffffff60208501511660208301526040840151612e2b604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b93565b60008060408385031215612e5557600080fd5b8235612e6081612856565b91506020830135612b7581612856565b600060608284031215612e8257600080fd5b610b9383836129ac565b600181811c90821680612ea057607f821691505b6020821081036128b6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612f2b57612f2b612ed9565b60405290565b6040805190810167ffffffffffffffff81118282101715612f2b57612f2b612ed9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f9b57612f9b612ed9565b604052919050565b600067ffffffffffffffff821115612fbd57612fbd612ed9565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600067ffffffffffffffff83111561300357613003612ed9565b8260051b61301360208201612f54565b8481529083019060208101903683111561302c57600080fd5b845b8381101561310b57803567ffffffffffffffff81111561304d57600080fd5b8601606036829003121561306057600080fd5b613068612f08565b61307182612aeb565b815261307f60208301612b97565b6020820152604082013567ffffffffffffffff81111561309e57600080fd5b919091019036601f8301126130b257600080fd5b81356130c56130c082612fa3565b612f54565b8181523660208386010111156130da57600080fd5b816020850160208301376000602083830101528060408401525050808552505060208301925060208101905061302e565b5095945050505050565b6000808585111561312557600080fd5b8386111561313257600080fd5b5050820193919092039150565b600084516131518184602089016127d5565b8201838582376000930192835250909392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610d6c602083018486613167565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261322757600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326657600080fd5b83018035915067ffffffffffffffff82111561328157600080fd5b602001915036819003821315612a0057600080fd5b67ffffffffffffffff8116811461140557600080fd5b63ffffffff6132ba89612aeb565b16815260208881013590820152600060408901356132d781613296565b67ffffffffffffffff811660408401525087606083015260e0608083015261330360e083018789613167565b73ffffffffffffffffffffffffffffffffffffffff861660a084015282810360c0840152613332818587613167565b9a9950505050505050505050565b60006020828403121561335257600080fd5b815167ffffffffffffffff81111561336957600080fd5b8201601f8101841361337a57600080fd5b80516133886130c082612fa3565b81815285602083850101111561339d57600080fd5b611af98260208301602086016127d5565b600060408284031280156133c157600080fd5b506133ca612f31565b823581526020928301359281019290925250919050565b6000602082840312156133f357600080fd5b8135610b9381613296565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015261ffff83166040820152608060608201526000610c0d60808301846127f9565b60408152600061345060408301856127f9565b8281036020840152611af981856127f9565b60006020828403121561347457600080fd5b8151610b9381612b20565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526134b560e08401826127f9565b905060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160a08501526134f082826127f9565b60809690960151151560c085015250505073ffffffffffffffffffffffffffffffffffffffff9190911660209091015290565b60006040828403121561353557600080fd5b61353d612f31565b825181526020928301519281019290925250919050565b60006040828403121561356657600080fd5b610b938383613523565b601f82111561144b57806000526020600020601f840160051c810160208510156135975750805b601f840160051c820191505b818110156112da57600081556001016135a3565b815167ffffffffffffffff8111156135d1576135d1612ed9565b6135e5816135df8454612e8c565b84613570565b6020601f82116001811461363757600083156136015750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556112da565b6000848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156136855787850151825560209485019460019092019101613665565b50848210156136c157868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015613772577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0878603018452815163ffffffff815116865261ffff6020820151166020870152604081015190506060604087015261375c60608701826127f9565b95505060209384019391909101906001016136f8565b50929695505050505050565b6000608082840312801561379157600080fd5b5061379a612f08565b8251815260208301516137ac81613296565b60208201526137be8460408501613523565b60408201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008261382f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761099d5761099d6137ca565b8035602083101561099d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081169060088410156138e6577fffffffffffffffff000000000000000000000000000000000000000000000000808560080360031b1b82161691505b5092915050565b7fffffffffffffffff0000000000000000000000000000000000000000000000008560c01b1681527fffffffff000000000000000000000000000000000000000000000000000000008460e01b16600882015282600c8201526000825161395b81602c8501602087016127d5565b91909101602c0195945050505050565b8082018082111561099d5761099d6137ca565b8481527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b166020820152826028820152600082516139c78160488501602087016127d5565b9190910160480195945050505050565b6000602082840312156139e957600080fd5b8151610b9381612856565b600082516132278184602087016127d556fea2646970667358221220d1c3f6c95e50de22b49ba7fe41b6d9d8c06fd27b8cbb411cf42a9ed68ee74d8264736f6c634300081a00330000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000a511e07689753fcf34d92b8ebb5bcdda385b7efd

Deployed Bytecode

0x6080604052600436106102d15760003560e01c80637d25a05e11610179578063bb0b6a53116100d6578063d045a0dc1161008a578063f2fde38b11610064578063f2fde38b146108b7578063fc0c546a14610515578063ff7bd03d146108d757600080fd5b8063d045a0dc14610831578063d424388514610844578063dd62ed3e1461086457600080fd5b8063bd815db0116100bb578063bd815db0146107dd578063c7c7f5b3146107f0578063ca5eb5e11461081157600080fd5b8063bb0b6a5314610790578063bc70b354146107bd57600080fd5b8063963efcaa1161012d578063a9059cbb11610112578063a9059cbb14610723578063b731ea0a14610743578063b98bd0701461077057600080fd5b8063963efcaa146106db5780639f68b9641461070f57600080fd5b8063857749b01161015e578063857749b0146106875780638da5cb5b1461069b57806395d89b41146106c657600080fd5b80637d25a05e1461062b57806382413eac1461066757600080fd5b806323b872dd116102325780635535d461116101e65780636fc1b31e116101c05780636fc1b31e146105b357806370a08231146105d3578063715018a61461061657600080fd5b80635535d461146105285780635a0dfe4d146105485780635e280f111461057f57600080fd5b80633400288b116102175780633400288b146104c85780633b6f743b146104e857806352ae28791461051557600080fd5b806323b872dd14610486578063313ce567146104a657600080fd5b8063134d4f251161028957806317442b701161026e57806317442b701461043057806318160ddd146104525780631f5e13341461047157600080fd5b8063134d4f25146103c7578063156a0d0f146103ef57600080fd5b80630d35b415116102ba5780630d35b41514610331578063111ecdad1461036057806313137d65146103b257600080fd5b806306fdde03146102d6578063095ea7b314610301575b600080fd5b3480156102e257600080fd5b506102eb6108f7565b6040516102f89190612843565b60405180910390f35b34801561030d57600080fd5b5061032161031c366004612878565b610989565b60405190151581526020016102f8565b34801561033d57600080fd5b5061035161034c3660046128bc565b6109a3565b6040516102f8939291906128f1565b34801561036c57600080fd5b5060045461038d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6103c56103c0366004612a07565b610a75565b005b3480156103d357600080fd5b506103dc600281565b60405161ffff90911681526020016102f8565b3480156103fb57600080fd5b50604080517f02e49c2c00000000000000000000000000000000000000000000000000000000815260016020820152016102f8565b34801561043c57600080fd5b50604080516001815260026020820152016102f8565b34801561045e57600080fd5b506007545b6040519081526020016102f8565b34801561047d57600080fd5b506103dc600181565b34801561049257600080fd5b506103216104a1366004612aaa565b610b74565b3480156104b257600080fd5b5060125b60405160ff90911681526020016102f8565b3480156104d457600080fd5b506103c56104e3366004612b04565b610b9a565b3480156104f457600080fd5b50610508610503366004612b2e565b610bb0565b6040516102f89190612b80565b34801561052157600080fd5b503061038d565b34801561053457600080fd5b506102eb610543366004612ba9565b610c17565b34801561055457600080fd5b50610321610563366004612b04565b63ffffffff919091166000908152600160205260409020541490565b34801561058b57600080fd5b5061038d7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b3480156105bf57600080fd5b506103c56105ce366004612bdc565b610cbc565b3480156105df57600080fd5b506104636105ee366004612bdc565b73ffffffffffffffffffffffffffffffffffffffff1660009081526005602052604090205490565b34801561062257600080fd5b506103c5610d3e565b34801561063757600080fd5b5061064e610646366004612b04565b600092915050565b60405167ffffffffffffffff90911681526020016102f8565b34801561067357600080fd5b50610321610682366004612bf9565b610d52565b34801561069357600080fd5b5060066104b6565b3480156106a757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661038d565b3480156106d257600080fd5b506102eb610d74565b3480156106e757600080fd5b506104637f000000000000000000000000000000000000000000000000000000e8d4a5100081565b34801561071b57600080fd5b506000610321565b34801561072f57600080fd5b5061032161073e366004612878565b610d83565b34801561074f57600080fd5b5060025461038d9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561077c57600080fd5b506103c561078b366004612ca5565b610d91565b34801561079c57600080fd5b506104636107ab366004612ce7565b60016020526000908152604090205481565b3480156107c957600080fd5b506102eb6107d8366004612d02565b610dab565b6103c56107eb366004612ca5565b610f6c565b6108036107fe366004612d63565b61113a565b6040516102f8929190612def565b34801561081d57600080fd5b506103c561082c366004612bdc565b611235565b6103c561083f366004612a07565b6112e1565b34801561085057600080fd5b506103c561085f366004612bdc565b611329565b34801561087057600080fd5b5061046361087f366004612e42565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260066020908152604080832093909416825291909152205490565b3480156108c357600080fd5b506103c56108d2366004612bdc565b6113a4565b3480156108e357600080fd5b506103216108f2366004612e70565b611408565b60606008805461090690612e8c565b80601f016020809104026020016040519081016040528092919081815260200182805461093290612e8c565b801561097f5780601f106109545761010080835404028352916020019161097f565b820191906000526020600020905b81548152906001019060200180831161096257829003601f168201915b5050505050905090565b60003361099781858561143e565b60019150505b92915050565b604080518082019091526000808252602082015260606109d6604051806040016040528060008152602001600081525090565b604080518082018252600080825267ffffffffffffffff602080840182905284518381529081019094529195509182610a32565b604080518082019091526000815260606020820152815260200190600190039081610a0a5790505b509350600080610a57604089013560608a0135610a5260208c018c612ce7565b611450565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff163314610aeb576040517f91ac5e4f0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b60208701803590610b0590610b00908a612ce7565b6114ad565b14610b5c57610b176020880188612ce7565b6040517fc26bebcc00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260208801356024820152604401610ae2565b610b6b87878787878787611502565b50505050505050565b600033610b8285828561169c565b610b8d85858561176b565b60019150505b9392505050565b610ba2611816565b610bac8282611869565b5050565b60408051808201909152600080825260208201526000610be060408501356060860135610a526020880188612ce7565b915050600080610bf086846118be565b9092509050610c0d610c056020880188612ce7565b838388611a14565b9695505050505050565b600360209081526000928352604080842090915290825290208054610c3b90612e8c565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6790612e8c565b8015610cb45780601f10610c8957610100808354040283529160200191610cb4565b820191906000526020600020905b815481529060010190602001808311610c9757829003601f168201915b505050505081565b610cc4611816565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610d46611816565b610d506000611b02565b565b73ffffffffffffffffffffffffffffffffffffffff811630145b949350505050565b60606009805461090690612e8c565b60003361099781858561176b565b610d99611816565b610bac610da68284612fe9565b611b77565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610ddf90612e8c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0b90612e8c565b8015610e585780601f10610e2d57610100808354040283529160200191610e58565b820191906000526020600020905b815481529060010190602001808311610e3b57829003601f168201915b505050505090508051600003610ea85783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610d6c9350505050565b6000839003610eb8579050610d6c565b60028310610f3657610eff84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c7e92505050565b80610f0d8460028188613115565b604051602001610f1f9392919061313f565b604051602081830303815290604052915050610d6c565b83836040517f9a6d49cd000000000000000000000000000000000000000000000000000000008152600401610ae29291906131b0565b60005b818110156110755736838383818110610f8a57610f8a6131c4565b9050602002810190610f9c91906131f3565b9050610fcf610fae6020830183612ce7565b602083013563ffffffff919091166000908152600160205260409020541490565b610fd9575061106d565b3063d045a0dc60c08301358360a0810135610ff8610100830183613231565b611009610100890160e08a01612bdc565b6110176101208a018a613231565b6040518963ffffffff1660e01b815260040161103997969594939291906132ac565b6000604051808303818588803b15801561105257600080fd5b505af1158015611066573d6000803e3d6000fd5b5050505050505b600101610f6f565b503373ffffffffffffffffffffffffffffffffffffffff16638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156110c1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111079190810190613340565b6040517f8351eea7000000000000000000000000000000000000000000000000000000008152600401610ae29190612843565b61114261278d565b604080518082019091526000808252602082015260008061117933604089013560608a013561117460208c018c612ce7565b611cc3565b9150915060008061118a89846118be565b90925090506111b661119f60208b018b612ce7565b83836111b0368d90038d018d6133ae565b8b611ce9565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611204908d018d612ce7565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b61123d611816565b6040517fca5eb5e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e190602401600060405180830381600087803b1580156112c657600080fd5b505af11580156112da573d6000803e3d6000fd5b5050505050565b33301461131a576040517f14d4a4e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b6b87878787878787610b5c565b611331611816565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610d33565b6113ac611816565b73ffffffffffffffffffffffffffffffffffffffff81166113fc576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b61140581611b02565b50565b60006020820180359060019083906114209086612ce7565b63ffffffff1681526020810191909152604001600020541492915050565b61144b8383836001611e01565b505050565b60008061145c85611f49565b9150819050838110156114a5576040517f71c4efed0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610ae2565b935093915050565b63ffffffff81166000908152600160205260408120548061099d576040517ff6ff4fb700000000000000000000000000000000000000000000000000000000815263ffffffff84166004820152602401610ae2565b60006115146115118787611f80565b90565b905060006115408261152e6115298a8a611f98565b611fbb565b61153b60208d018d612ce7565b611ff1565b9050602886111561162d57600061157d61156060608c0160408d016133e1565b61156d60208d018d612ce7565b846115788c8c612026565b612071565b6040517f7cb5901200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690637cb59012906115f99086908d9060009087906004016133fe565b600060405180830381600087803b15801561161357600080fd5b505af1158015611627573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff8216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61167360208d018d612ce7565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600660209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146117655781811015611756576040517ffb8f41b200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024810182905260448101839052606401610ae2565b61176584848484036000611e01565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166117bb576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff821661180b576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b61144b8383836120a3565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d50576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610ae2565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061191b85602001356118d48661224e565b6118e160a0890189613231565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061227a92505050565b909350905060008161192e576001611931565b60025b90506119516119436020880188612ce7565b826107d860808a018a613231565b60045490935073ffffffffffffffffffffffffffffffffffffffff168015611a0a576040517f043a78eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063043a78eb906119c7908890889060040161343d565b602060405180830381865afa1580156119e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a089190613462565b505b5050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff1663ddc28c586040518060a001604052808863ffffffff168152602001611a84896114ad565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611ab992919061347f565b6040805180830381865afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190613554565b95945050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c4e57611ba9828281518110611b9857611b986131c4565b602002602001015160400151611c7e565b818181518110611bbb57611bbb6131c4565b60200260200101516040015160036000848481518110611bdd57611bdd6131c4565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c1757611c176131c4565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c4591906135b7565b50600101611b7a565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610d3391906136d0565b600281015161ffff8116600314610bac57816040517f9a6d49cd000000000000000000000000000000000000000000000000000000008152600401610ae29190612843565b600080611cd1858585611450565b9092509050611ce0868361230c565b94509492505050565b611cf161278d565b6000611d008460000151612368565b602085015190915015611d1a57611d1a84602001516123a9565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff16632637a450826040518060a001604052808b63ffffffff168152602001611d778c6114ad565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611db392919061347f565b60806040518083038185885af1158015611dd1573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611df6919061377e565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416611e51576040517fe602df0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff8316611ea1576040517f94280d6200000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526006602090815260408083209387168352929052208290558015611765578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611f3b91815260200190565b60405180910390a350505050565b60007f000000000000000000000000000000000000000000000000000000e8d4a51000611f7681846137f9565b61099d9190613834565b6000611f8f6020828486613115565b610b939161384b565b6000611fa8602860208486613115565b611fb191613887565b60c01c9392505050565b600061099d7f000000000000000000000000000000000000000000000000000000e8d4a5100067ffffffffffffffff8416613834565b600073ffffffffffffffffffffffffffffffffffffffff84166120145761dead93505b61201e84846124cb565b509092915050565b60606120358260288186613115565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161208a94939291906138ed565b6040516020818303038152906040529050949350505050565b73ffffffffffffffffffffffffffffffffffffffff83166120db5780600760008282546120d0919061396b565b9091555061218d9050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602052604090205481811015612161576040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024810182905260448101839052606401610ae2565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602052604090209082900390555b73ffffffffffffffffffffffffffffffffffffffff82166121b6576007805482900390556121e2565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090208054820190555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161224191815260200190565b60405180910390a3505050565b600061099d7f000000000000000000000000000000000000000000000000000000e8d4a51000836137f9565b80516060901515806122db5784846040516020016122c792919091825260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b604051602081830303815290604052612302565b848433856040516020016122f2949392919061397e565b6040516020818303038152906040525b9150935093915050565b73ffffffffffffffffffffffffffffffffffffffff821661235c576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b610bac826000836120a3565b60008134146123a5576040517f9f704120000000000000000000000000000000000000000000000000000000008152346004820152602401610ae2565b5090565b60007f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff1663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a91906139d7565b905073ffffffffffffffffffffffffffffffffffffffff8116612489576040517f5373352a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bac73ffffffffffffffffffffffffffffffffffffffff8216337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c85612527565b73ffffffffffffffffffffffffffffffffffffffff821661251b576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401610ae2565b610bac600083836120a3565b6040805173ffffffffffffffffffffffffffffffffffffffff8581166024830152848116604483015260648083018590528351808403909101815260849092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052611765918691906000906125c89084168361263c565b905080516000141580156125ed5750808060200190518101906125eb9190613462565b155b1561144b576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610ae2565b6060610b9383836000846000808573ffffffffffffffffffffffffffffffffffffffff16848660405161266f91906139f4565b60006040518083038185875af1925050503d80600081146126ac576040519150601f19603f3d011682016040523d82523d6000602084013e6126b1565b606091505b5091509150610c0d8683836060826126d1576126cc8261274b565b610b93565b81511580156126f5575073ffffffffffffffffffffffffffffffffffffffff84163b155b15612744576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610ae2565b5080610b93565b80511561275b5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051806060016040528060008019168152602001600067ffffffffffffffff1681526020016127d0604051806040016040528060008152602001600081525090565b905290565b60005b838110156127f05781810151838201526020016127d8565b50506000910152565b600081518084526128118160208601602086016127d5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b9360208301846127f9565b73ffffffffffffffffffffffffffffffffffffffff8116811461140557600080fd5b6000806040838503121561288b57600080fd5b823561289681612856565b946020939093013593505050565b600060e082840312156128b657600080fd5b50919050565b6000602082840312156128ce57600080fd5b813567ffffffffffffffff8111156128e557600080fd5b610d6c848285016128a4565b8351815260208085015190820152600060a0820160a0604084015280855180835260c08501915060c08160051b86010192506020870160005b82811015612990577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40878603018452815180518652602081015190506040602087015261297a60408701826127f9565b955050602093840193919091019060010161292a565b5050855160608601525050602084015160808401529050610d6c565b6000606082840312156128b657600080fd5b60008083601f8401126129d057600080fd5b50813567ffffffffffffffff8111156129e857600080fd5b602083019150836020828501011115612a0057600080fd5b9250929050565b600080600080600080600060e0888a031215612a2257600080fd5b612a2c89896129ac565b965060608801359550608088013567ffffffffffffffff811115612a4f57600080fd5b612a5b8a828b016129be565b90965094505060a0880135612a6f81612856565b925060c088013567ffffffffffffffff811115612a8b57600080fd5b612a978a828b016129be565b989b979a50959850939692959293505050565b600080600060608486031215612abf57600080fd5b8335612aca81612856565b92506020840135612ada81612856565b929592945050506040919091013590565b803563ffffffff81168114612aff57600080fd5b919050565b60008060408385031215612b1757600080fd5b61289683612aeb565b801515811461140557600080fd5b60008060408385031215612b4157600080fd5b823567ffffffffffffffff811115612b5857600080fd5b612b64858286016128a4565b9250506020830135612b7581612b20565b809150509250929050565b81518152602080830151908201526040810161099d565b803561ffff81168114612aff57600080fd5b60008060408385031215612bbc57600080fd5b612bc583612aeb565b9150612bd360208401612b97565b90509250929050565b600060208284031215612bee57600080fd5b8135610b9381612856565b60008060008060a08587031215612c0f57600080fd5b612c1986866129ac565b9350606085013567ffffffffffffffff811115612c3557600080fd5b612c41878288016129be565b9094509250506080850135612c5581612856565b939692955090935050565b60008083601f840112612c7257600080fd5b50813567ffffffffffffffff811115612c8a57600080fd5b6020830191508360208260051b8501011115612a0057600080fd5b60008060208385031215612cb857600080fd5b823567ffffffffffffffff811115612ccf57600080fd5b612cdb85828601612c60565b90969095509350505050565b600060208284031215612cf957600080fd5b610b9382612aeb565b60008060008060608587031215612d1857600080fd5b612d2185612aeb565b9350612d2f60208601612b97565b9250604085013567ffffffffffffffff811115612d4b57600080fd5b612d57878288016129be565b95989497509550505050565b60008060008385036080811215612d7957600080fd5b843567ffffffffffffffff811115612d9057600080fd5b612d9c878288016128a4565b94505060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082011215612dcf57600080fd5b506020840191506060840135612de481612856565b809150509250925092565b600060c0820190508351825267ffffffffffffffff60208501511660208301526040840151612e2b604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b93565b60008060408385031215612e5557600080fd5b8235612e6081612856565b91506020830135612b7581612856565b600060608284031215612e8257600080fd5b610b9383836129ac565b600181811c90821680612ea057607f821691505b6020821081036128b6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612f2b57612f2b612ed9565b60405290565b6040805190810167ffffffffffffffff81118282101715612f2b57612f2b612ed9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f9b57612f9b612ed9565b604052919050565b600067ffffffffffffffff821115612fbd57612fbd612ed9565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600067ffffffffffffffff83111561300357613003612ed9565b8260051b61301360208201612f54565b8481529083019060208101903683111561302c57600080fd5b845b8381101561310b57803567ffffffffffffffff81111561304d57600080fd5b8601606036829003121561306057600080fd5b613068612f08565b61307182612aeb565b815261307f60208301612b97565b6020820152604082013567ffffffffffffffff81111561309e57600080fd5b919091019036601f8301126130b257600080fd5b81356130c56130c082612fa3565b612f54565b8181523660208386010111156130da57600080fd5b816020850160208301376000602083830101528060408401525050808552505060208301925060208101905061302e565b5095945050505050565b6000808585111561312557600080fd5b8386111561313257600080fd5b5050820193919092039150565b600084516131518184602089016127d5565b8201838582376000930192835250909392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610d6c602083018486613167565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261322757600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326657600080fd5b83018035915067ffffffffffffffff82111561328157600080fd5b602001915036819003821315612a0057600080fd5b67ffffffffffffffff8116811461140557600080fd5b63ffffffff6132ba89612aeb565b16815260208881013590820152600060408901356132d781613296565b67ffffffffffffffff811660408401525087606083015260e0608083015261330360e083018789613167565b73ffffffffffffffffffffffffffffffffffffffff861660a084015282810360c0840152613332818587613167565b9a9950505050505050505050565b60006020828403121561335257600080fd5b815167ffffffffffffffff81111561336957600080fd5b8201601f8101841361337a57600080fd5b80516133886130c082612fa3565b81815285602083850101111561339d57600080fd5b611af98260208301602086016127d5565b600060408284031280156133c157600080fd5b506133ca612f31565b823581526020928301359281019290925250919050565b6000602082840312156133f357600080fd5b8135610b9381613296565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015261ffff83166040820152608060608201526000610c0d60808301846127f9565b60408152600061345060408301856127f9565b8281036020840152611af981856127f9565b60006020828403121561347457600080fd5b8151610b9381612b20565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526134b560e08401826127f9565b905060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160a08501526134f082826127f9565b60809690960151151560c085015250505073ffffffffffffffffffffffffffffffffffffffff9190911660209091015290565b60006040828403121561353557600080fd5b61353d612f31565b825181526020928301519281019290925250919050565b60006040828403121561356657600080fd5b610b938383613523565b601f82111561144b57806000526020600020601f840160051c810160208510156135975750805b601f840160051c820191505b818110156112da57600081556001016135a3565b815167ffffffffffffffff8111156135d1576135d1612ed9565b6135e5816135df8454612e8c565b84613570565b6020601f82116001811461363757600083156136015750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556112da565b6000848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b828110156136855787850151825560209485019460019092019101613665565b50848210156136c157868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015613772577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0878603018452815163ffffffff815116865261ffff6020820151166020870152604081015190506060604087015261375c60608701826127f9565b95505060209384019391909101906001016136f8565b50929695505050505050565b6000608082840312801561379157600080fd5b5061379a612f08565b8251815260208301516137ac81613296565b60208201526137be8460408501613523565b60408201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008261382f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761099d5761099d6137ca565b8035602083101561099d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b80357fffffffffffffffff00000000000000000000000000000000000000000000000081169060088410156138e6577fffffffffffffffff000000000000000000000000000000000000000000000000808560080360031b1b82161691505b5092915050565b7fffffffffffffffff0000000000000000000000000000000000000000000000008560c01b1681527fffffffff000000000000000000000000000000000000000000000000000000008460e01b16600882015282600c8201526000825161395b81602c8501602087016127d5565b91909101602c0195945050505050565b8082018082111561099d5761099d6137ca565b8481527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b166020820152826028820152600082516139c78160488501602087016127d5565b9190910160480195945050505050565b6000602082840312156139e957600080fd5b8151610b9381612856565b600082516132278184602087016127d556fea2646970667358221220d1c3f6c95e50de22b49ba7fe41b6d9d8c06fd27b8cbb411cf42a9ed68ee74d8264736f6c634300081a0033

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

0000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000a511e07689753fcf34d92b8ebb5bcdda385b7efd

-----Decoded View---------------
Arg [0] : _lzEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [1] : _delegate (address): 0xA511e07689753fcF34d92B8Ebb5BcDDa385b7eFd

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [1] : 000000000000000000000000a511e07689753fcf34d92b8ebb5bcdda385b7efd


Deployed Bytecode Sourcemap

254:321:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89:31;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4293:186;;;;;;;;;;-1:-1:-1;4293:186:31;;;;;:::i;:::-;;:::i;:::-;;;1525:14:40;;1518:22;1500:41;;1488:2;1473:18;4293:186:31;1360:187:40;5052:1258:25;;;;;;;;;;-1:-1:-1;5052:1258:25;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2256:27::-;;;;;;;;;;-1:-1:-1;2256:27:25;;;;;;;;;;;3773:42:40;3761:55;;;3743:74;;3731:2;3716:18;2256:27:25;3597:226:40;4368:708:13;;;;;;:::i;:::-;;:::i;:::-;;2130:40:25;;;;;;;;;;;;2169:1;2130:40;;;;;5611:6:40;5599:19;;;5581:38;;5569:2;5554:18;2130:40:25;5437:188:40;3401:140:25;;;;;;;;;;-1:-1:-1;3401:140:25;;;3508:22;5800:98:40;;3532:1:25;5929:2:40;5914:18;;5907:59;5773:18;3401:140:25;5630:342:40;1287:235:11;;;;;;;;;;-1:-1:-1;1287:235:11;;;843:1:14;6147:50:40;;678:1:13;6228:2:40;6213:18;;6206:59;6120:18;1287:235:11;5977:294:40;3144:97:31;;;;;;;;;;-1:-1:-1;3222:12:31;;3144:97;;;6422:25:40;;;6410:2;6395:18;3144:97:31;6276:177:40;2093:31:25;;;;;;;;;;;;2123:1;2093:31;;5039:244:31;;;;;;;;;;-1:-1:-1;5039:244:31;;;;;:::i;:::-;;:::i;3002:82::-;;;;;;;;;;-1:-1:-1;3075:2:31;3002:82;;;7143:4:40;7131:17;;;7113:36;;7101:2;7086:18;3002:82:31;6971:184:40;1724:108:12;;;;;;;;;;-1:-1:-1;1724:108:12;;;;;:::i;:::-;;:::i;6761:774:25:-;;;;;;;;;;-1:-1:-1;6761:774:25;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;875:93:20:-;;;;;;;;;;-1:-1:-1;956:4:20;875:93;;538::19;;;;;;;;;;-1:-1:-1;538:93:19;;;;;:::i;:::-;;:::i;15018:132:25:-;;;;;;;;;;-1:-1:-1;15018:132:25;;;;;:::i;:::-;15123:11;;;;;15100:4;15123:11;;;:5;:11;;;;;;:20;;15018:132;446:46:12;;;;;;;;;;;;;;;4583:163:25;;;;;;;;;;-1:-1:-1;4583:163:25;;;;;:::i;:::-;;:::i;3299:116:31:-;;;;;;;;;;-1:-1:-1;3299:116:31;;;;;:::i;:::-;3390:18;;3364:7;3390:18;;;:9;:18;;;;;;;3299:116;2293:101:29;;;;;;;;;;;;;:::i;3507:128:13:-;;;;;;;;;;-1:-1:-1;3507:128:13;;;;;:::i;:::-;3596:12;3507:128;;;;;;;;9839:18:40;9827:31;;;9809:50;;9797:2;9782:18;3507:128:13;9665:200:40;2013:216:13;;;;;;;;;;-1:-1:-1;2013:216:13;;;;;:::i;:::-;;:::i;4148:87:25:-;;;;;;;;;;-1:-1:-1;4227:1:25;4148:87;;1638:85:29;;;;;;;;;;-1:-1:-1;1684:7:29;1710:6;;;1638:85;;2276:93:31;;;;;;;;;;;;;:::i;1787:46:25:-;;;;;;;;;;;;;;;1460:94:24;;;;;;;;;;-1:-1:-1;1519:4:24;1460:94;;3610:178:31;;;;;;;;;;-1:-1:-1;3610:178:31;;;;;:::i;:::-;;:::i;559:23:20:-;;;;;;;;;;-1:-1:-1;559:23:20;;;;;;;;1391:156:19;;;;;;;;;;-1:-1:-1;1391:156:19;;;;;:::i;:::-;;:::i;569:48:12:-;;;;;;;;;;-1:-1:-1;569:48:12;;;;;:::i;:::-;;;;;;;;;;;;;;3510:981:19;;;;;;;;;;-1:-1:-1;3510:981:19;;;;;:::i;:::-;;:::i;1698:1333:20:-;;;;;;:::i;:::-;;:::i;8223:1340:25:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;3252:105:12:-;;;;;;;;;;-1:-1:-1;3252:105:12;;;;;:::i;:::-;;:::i;3679:409:20:-;;;;;;:::i;:::-;;:::i;1100:139::-;;;;;;;;;;-1:-1:-1;1100:139:20;;;;;:::i;:::-;;:::i;3846:140:31:-;;;;;;;;;;-1:-1:-1;3846:140:31;;;;;:::i;:::-;3952:18;;;;3926:7;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3846:140;2543:215:29;;;;;;;;;;-1:-1:-1;2543:215:29;;;;;:::i;:::-;;:::i;2771:149:13:-;;;;;;;;;;-1:-1:-1;2771:149:13;;;;;:::i;:::-;;:::i;2074:89:31:-;2119:13;2151:5;2144:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89;:::o;4293:186::-;4366:4;735:10:37;4420:31:31;735:10:37;4436:7:31;4445:5;4420:8;:31::i;:::-;4468:4;4461:11;;;4293:186;;;;;:::o;5052:1258:25:-;-1:-1:-1;;;;;;;;;;;;;;;;;5204:35:25;5241:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;5241:28:25;5459:34;;;;;;;;-1:-1:-1;5459:34:25;;;5381:16;5459:34;;;;;;;5610:21;;;;;;;;;;;5459:34;;-1:-1:-1;;;5610:21:25;;;-1:-1:-1;;;;;;;;;;;;;;;;;5610:21:25;;;;;;;;;;;;;;;-1:-1:-1;5594:37:25;-1:-1:-1;6068:20:25;;6118:120;6142:19;;;;6175:22;;;;6211:17;;;;6142:10;6211:17;:::i;:::-;6118:10;:120::i;:::-;6261:42;;;;;;;;;;;;;;;;5052:1258;;;;-1:-1:-1;;;;;;5052:1258:25:o;4368:708:13:-;4681:8;4673:31;;4694:10;4673:31;4669:68;;4713:24;;;;;4726:10;4713:24;;;3743:74:40;3716:18;;4713:24:13;;;;;;;;4669:68;4873:14;;;;;;4837:32;;4854:14;;4873:7;4854:14;:::i;:::-;4837:16;:32::i;:::-;:50;4833:103;;4905:14;;;;:7;:14;:::i;:::-;4896:40;;;;;15682:10:40;15670:23;;;4896:40:13;;;15652:42:40;4921:14:13;;;;15710:18:40;;;15703:34;15625:18;;4896:40:13;15480:263:40;4833:103:13;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;5039:244:31:-;5126:4;735:10:37;5182:37:31;5198:4;735:10:37;5213:5:31;5182:15;:37::i;:::-;5229:26;5239:4;5245:2;5249:5;5229:9;:26::i;:::-;5272:4;5265:11;;;5039:244;;;;;;:::o;1724:108:12:-;1531:13:29;:11;:13::i;:::-;1804:21:12::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;6761:774:25:-;-1:-1:-1;;;;;;;;;;;;;;;;;7095:24:25;7123:74;7134:19;;;;7155:22;;;;7179:17;;;;7134:10;7179:17;:::i;7123:74::-;7092:105;;;7286:20;7308;7332:49;7352:10;7364:16;7332:19;:49::i;:::-;7285:96;;-1:-1:-1;7285:96:25;-1:-1:-1;7470:58:25;7477:17;;;;:10;:17;:::i;:::-;7496:7;7505;7514:13;7470:6;:58::i;:::-;7463:65;6761:774;-1:-1:-1;;;;;;6761:774:25:o;538:93:19:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4583:163:25:-;1531:13:29;:11;:13::i;:::-;4666:12:25::1;:28:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;4709:30:::1;::::0;3743:74:40;;;4709:30:25::1;::::0;3731:2:40;3716:18;4709:30:25::1;;;;;;;;4583:163:::0;:::o;2293:101:29:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;2013:216:13:-;2198:24;;;2217:4;2198:24;2013:216;;;;;;;:::o;2276:93:31:-;2323:13;2355:7;2348:14;;;;;:::i;3610:178::-;3679:4;735:10:37;3733:27:31;735:10:37;3750:2:31;3754:5;3733:9;:27::i;1391:156:19:-;1531:13:29;:11;:13::i;:::-;1503:37:19::1;;1523:16:::0;;1503:37:::1;:::i;:::-;:19;:37::i;3510:981::-:0;3701:21;;;3677;3701;;;:15;:21;;;;;;;;:31;;;;;;;;;;3677:55;;3653:12;;3677:21;3701:31;3677:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:8;:15;3880:1;3861:20;3857:46;;3890:13;;3883:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3883:20:19;;-1:-1:-1;3883:20:19;;-1:-1:-1;;;;3883:20:19;3857:46;3988:1;3964:25;;;3960:46;;3998:8;-1:-1:-1;3991:15:19;;3960:46;4153:1;4129:25;;4125:267;;4170:34;4190:13;;4170:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4170:19:19;;-1:-1:-1;;;4170:34:19:i;:::-;4353:8;4363:17;:13;4377:1;4363:13;;:17;:::i;:::-;4340:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4333:48;;;;;4125:267;4470:13;;4455:29;;;;;;;;;;;;:::i;1698:1333:20:-;1799:9;1794:1037;1814:19;;;1794:1037;;;1854:29;1886:8;;1895:1;1886:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;1854:43;-1:-1:-1;1980:50:20;1987:20;;;;1854:43;1987:20;:::i;:::-;2009;;;;15123:11:25;;;;;15100:4;15123:11;;;:5;:11;;;;;;:20;;15018:132;1980:50:20;1975:65;;2032:8;;;1975:65;2602:4;:22;2633:12;;;;:6;2696:11;;;;2725:14;;;;2633:6;2725:14;:::i;:::-;2757:15;;;;;;;;:::i;:::-;2790:16;;;;:6;:16;:::i;:::-;2602:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1840:991;1794:1037;1835:3;;1794:1037;;;;2988:10;2978:43;;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2961:63;;;;;;;;;;;:::i;8223:1340:25:-;8384:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;8782:20:25;;8832:140;8852:10;8876:19;;;;8909:22;;;;8945:17;;;;8876:10;8945:17;:::i;:::-;8832:6;:140::i;:::-;8781:191;;;;9061:20;9083;9107:49;9127:10;9139:16;9107:19;:49::i;:::-;9060:96;;-1:-1:-1;9060:96:25;-1:-1:-1;9279:66:25;9287:17;;;;:10;:17;:::i;:::-;9306:7;9315;9279:66;;;;;;;9324:4;9279:66;:::i;:::-;9330:14;9279:7;:66::i;:::-;9411:42;;;;;;;;;;;;;;;;;;;9477:15;;9266:79;;-1:-1:-1;9411:42:25;;-1:-1:-1;9513:10:25;;9477:15;9469:87;;9494:17;;;;:10;:17;:::i;:::-;9469:87;;;23800:10:40;23788:23;;;23770:42;;23843:2;23828:18;;23821:34;;;23871:18;;23864:34;;;23758:2;23743:18;9469:87:25;;;;;;;8450:1113;;;;8223:1340;;;;;;:::o;3252:105:12:-;1531:13:29;:11;:13::i;:::-;3319:31:12::1;::::0;;;;:20:::1;3761:55:40::0;;;3319:31:12::1;::::0;::::1;3743:74:40::0;3319:8:12::1;:20;::::0;::::1;::::0;3716:18:40;;3319:31:12::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3252:105:::0;:::o;3679:409:20:-;3958:10;3980:4;3958:27;3954:50;;3994:10;;;;;;;;;;;;;;3954:50;4014:67;4033:7;4042:5;4049:8;;4059:9;4070:10;;4014:18;:67::i;1100:139::-;1531:13:29;:11;:13::i;:::-;1175:8:20::1;:20:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;1210:22:::1;::::0;3743:74:40;;;1210:22:20::1;::::0;3731:2:40;3716:18;1210:22:20::1;3597:226:40::0;2543:215:29;1531:13;:11;:13::i;:::-;2627:22:::1;::::0;::::1;2623:91;;2672:31;::::0;::::1;::::0;;2700:1:::1;2672:31;::::0;::::1;3743:74:40::0;3716:18;;2672:31:29::1;3597:226:40::0;2623:91:29::1;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;2771:149:13:-;2853:4;2900:13;;;;;;2876:5;;2853:4;;2882:13;;2900:6;2882:13;:::i;:::-;2876:20;;;;;;;;;;;;;-1:-1:-1;2876:20:13;;:37;;2771:149;-1:-1:-1;;2771:149:13:o;8989:128:31:-;9073:37;9082:5;9089:7;9098:5;9105:4;9073:8;:37::i;:::-;8989:128;;;:::o;17035:668:25:-;17177:20;17199:24;17373:22;17385:9;17373:11;:22::i;:::-;17358:37;;17521:12;17502:31;;17603:12;17584:16;:31;17580:117;;;17638:48;;;;;;;;24083:25:40;;;24124:18;;;24117:34;;;24056:18;;17638:48:25;23909:248:40;17580:117:25;17035:668;;;;;;:::o;2718:196:12:-;2822:11;;;2788:7;2822:11;;;:5;:11;;;;;;;2843:43;;2874:12;;;;;24336:10:40;24324:23;;2874:12:12;;;24306:42:40;24279:18;;2874:12:12;24162:192:40;11811:1806:25;12288:17;12308:36;:17;:8;;:15;:17::i;:::-;2891:2:28;2780:123;12308:36:25;12288:56;;12477:24;12504:62;12512:9;12523:26;12529:19;:8;;:17;:19::i;:::-;12523:5;:26::i;:::-;12551:14;;;;:7;:14;:::i;:::-;12504:7;:62::i;:::-;12477:89;-1:-1:-1;243:2:28;-1:-1:-1;;12577:955:25;;;12681:23;12707:175;12750:13;;;;;;;;:::i;:::-;12781:14;;;;:7;:14;:::i;:::-;12813:16;12847:21;:8;;:19;:21::i;:::-;12707:25;:175::i;:::-;13429:92;;;;;12681:201;;-1:-1:-1;13429:20:25;:8;:20;;;;:92;;13450:9;;13461:5;;13468:1;;12681:201;;13429:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12604:928;12577:955;13547:63;;;13559:5;13547:63;13566:14;;;;:7;:14;:::i;:::-;13547:63;;;15682:10:40;15670:23;;;15652:42;;15725:2;15710:18;;15703:34;;;15625:18;13547:63:25;;;;;;;12114:1503;;11811:1806;;;;;;;:::o;10663:477:31:-;3952:18;;;;10762:24;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;10848:17;10828:37;;10824:310;;10904:5;10885:16;:24;10881:130;;;10936:60;;;;;25616:42:40;25604:55;;10936:60:31;;;25586:74:40;25676:18;;;25669:34;;;25719:18;;;25712:34;;;25559:18;;10936:60:31;25384:368:40;10881:130:31;11052:57;11061:5;11068:7;11096:5;11077:16;:24;11103:5;11052:8;:57::i;:::-;10752:388;10663:477;;;:::o;5656:300::-;5739:18;;;5735:86;;5780:30;;;;;5807:1;5780:30;;;3743:74:40;3716:18;;5780:30:31;3597:226:40;5735:86:31;5834:16;;;5830:86;;5873:32;;;;;5902:1;5873:32;;;3743:74:40;3716:18;;5873:32:31;3597:226:40;5830:86:31;5925:24;5933:4;5939:2;5943:5;5925:7;:24::i;1796:162:29:-;1684:7;1710:6;1855:23;1710:6;735:10:37;1855:23:29;1851:101;;1901:40;;;;;735:10:37;1901:40:29;;;3743:74:40;3716:18;;1901:40:29;3597:226:40;2286:134:12;2359:11;;;;;;;:5;:11;;;;;;;;;:19;;;2393:20;;15652:42:40;;;15710:18;;15703:34;;;2393:20:12;;15625:18:40;2393:20:12;;;;;;;2286:134;;:::o;9857:1436:25:-;9989:20;10011;10043:15;10214:324;10246:10;:13;;;10273:16;10279:9;10273:5;:16::i;:::-;10507:21;;;;:10;:21;:::i;:::-;10214:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10214:18:25;;-1:-1:-1;;;10214:324:25:i;:::-;10190:348;;-1:-1:-1;10190:348:25;-1:-1:-1;10618:14:25;10190:348;10635:33;;2123:1;10635:33;;;2169:1;10635:33;10618:50;-1:-1:-1;10790:67:25;10805:17;;;;:10;:17;:::i;:::-;10824:7;10833:23;;;;:10;:23;:::i;10790:67::-;11115:12;;10780:77;;-1:-1:-1;11115:12:25;;11207:23;;11203:83;;11232:54;;;;;:36;;;;;;:54;;11269:7;;11278;;11232:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;11203:83;10033:1260;;;9857:1436;;;;;:::o;2038:391:14:-;-1:-1:-1;;;;;;;;;;;;;;;;;2259:8:14;:14;;;2291:86;;;;;;;;2307:7;2291:86;;;;;;2316:25;2333:7;2316:16;:25::i;:::-;2291:86;;;;2343:8;2291:86;;;;2353:8;2291:86;;;;2363:13;2291:86;;;;;2403:4;2259:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2240:182;2038:391;-1:-1:-1;;;;;2038:391:14:o;2912:187:29:-;2985:16;3004:6;;;3020:17;;;;;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;2237:514:19:-;2345:9;2340:354;2364:16;:23;2360:1;:27;2340:354;;;2522:48;2542:16;2559:1;2542:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2522:19;:48::i;:::-;2656:16;2673:1;2656:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:15;:40;2600:16;2617:1;2600:19;;;;;;;;:::i;:::-;;;;;;;:23;;;2584:40;;;;;;;;;;;;;;;:69;2625:16;2642:1;2625:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:69;;;;;;;;;;;;;;;:99;;;;;;:::i;:::-;-1:-1:-1;2389:3:19;;2340:354;;;;2709:35;2727:16;2709:35;;;;;;:::i;4631:264::-;4801:1;4787:16;;4781:23;4827:28;;;463:1;4827:28;4823:65;;4879:8;4864:24;;;;;;;;;;;:::i;2037:567:24:-;2198:20;2220:24;2291:44;2302:9;2313:12;2327:7;2291:10;:44::i;:::-;2256:79;;-1:-1:-1;2256:79:24;-1:-1:-1;2571:26:24;2577:5;2256:79;2571:5;:26::i;:::-;2037:567;;;;;;;:::o;3188:766:14:-;3389:31;;:::i;:::-;3554:20;3577:26;3588:4;:14;;;3577:10;:26::i;:::-;3617:15;;;;3554:49;;-1:-1:-1;3617:19:14;3613:53;;3638:28;3650:4;:15;;;3638:11;:28::i;:::-;3755:8;:13;;;3777:12;3809:92;;;;;;;;3825:7;3809:92;;;;;;3834:25;3851:7;3834:16;:25::i;:::-;3809:92;;;;3861:8;3809:92;;;;3871:8;3809:92;;;;3899:1;3881:4;:15;;;:19;3809:92;;;;;3919:14;3755:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3677:270;3188:766;-1:-1:-1;;;;;;;3188:766:14:o;9949:432:31:-;10061:19;;;10057:89;;10103:32;;;;;10132:1;10103:32;;;3743:74:40;3716:18;;10103:32:31;3597:226:40;10057:89:31;10159:21;;;10155:90;;10203:31;;;;;10231:1;10203:31;;;3743:74:40;3716:18;;10203:31:31;3597:226:40;10155:90:31;10254:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10299:76;;;;10349:7;10333:31;;10342:5;10333:31;;;10358:5;10333:31;;;;6422:25:40;;6410:2;6395:18;;6276:177;10333:31:31;;;;;;;;9949:432;;;;:::o;15544:172:25:-;15615:16;15688:21;15651:33;15688:21;15651:9;:33;:::i;:::-;15650:59;;;;:::i;1573:123:28:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:28:o;15940:139:25:-;16004:16;16039:33;16051:21;16039:33;;;;:::i;2939:462:24:-;3073:24;3113:19;;;3109:46;;3148:6;3134:21;;3109:46;3251:21;3257:3;3262:9;3251:5;:21::i;:::-;-1:-1:-1;3385:9:24;;2939:462;-1:-1:-1;;2939:462:24:o;2186:130:28:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:28;;2186:130;-1:-1:-1;;;;;;2186:130:28:o;640:284:27:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;6271:1107:31:-;6360:18;;;6356:540;;6512:5;6496:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6356:540:31;;-1:-1:-1;6356:540:31;;6570:15;;;6548:19;6570:15;;;:9;:15;;;;;;6603:19;;;6599:115;;;6649:50;;;;;25616:42:40;25604:55;;6649:50:31;;;25586:74:40;25676:18;;;25669:34;;;25719:18;;;25712:34;;;25559:18;;6649:50:31;25384:368:40;6599:115:31;6834:15;;;;;;;:9;:15;;;;;6852:19;;;;6834:37;;6356:540;6910:16;;;6906:425;;7073:12;:21;;;;;;;6906:425;;;7284:13;;;;;;;:9;:13;;;;;:22;;;;;;6906:425;7361:2;7346:25;;7355:4;7346:25;;;7365:5;7346:25;;;;6422::40;;6410:2;6395:18;;6276:177;7346:25:31;;;;;;;;6271:1107;;;:::o;16303:147:25:-;16368:15;16409:33;16421:21;16409:9;:33;:::i;598:506:28:-;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;34429:19:40;;;34486:3;34482:16;34500:66;34478:89;34473:2;34464:12;;34457:111;34593:2;34584:12;;34274:328;1057:40:28;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;8247:206:31:-;8317:21;;;8313:89;;8361:30;;;;;8388:1;8361:30;;;3743:74:40;3716:18;;8361:30:31;3597:226:40;8313:89:31;8411:35;8419:7;8436:1;8440:5;8411:7;:35::i;4650:191:14:-;4716:17;4762:10;4749:9;:23;4745:62;;4781:26;;;;;4797:9;4781:26;;;6422:25:40;6395:18;;4781:26:14;6276:177:40;4745:62:14;-1:-1:-1;4824:10:14;4650:191::o;5218:410::-;5371:15;5389:8;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5371:36;-1:-1:-1;5421:21:14;;;5417:54;;5451:20;;;;;;;;;;;;;;5417:54;5545:76;:32;;;5578:10;5598:8;5609:11;5545:32;:76::i;7721:208:31:-;7791:21;;;7787:91;;7835:32;;;;;7864:1;7835:32;;;3743:74:40;3716:18;;7835:32:31;3597:226:40;7787:91:31;7887:35;7903:1;7907:7;7916:5;7887:7;:35::i;1702:188:35:-;1829:53;;;1844:18;35658:55:40;;;1829:53:35;;;35640:74:40;35750:55;;;35730:18;;;35723:83;35822:18;;;;35815:34;;;1829:53:35;;;;;;;;;;35613:18:40;;;;1829:53:35;;;;;;;;;;;;;;1802:81;;1822:5;;1829:53;-1:-1:-1;;4504:33:35;;1844:18;;1829:53;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;;;;3773:42:40;3761:55;;4631:40:35;;;3743:74:40;3716:18;;4631:40:35;3597:226:40;2705:151:36;2780:12;2811:38;2833:6;2841:4;2847:1;2780:12;3421;3435:23;3462:6;:11;;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;5071:18:36;;;;:23;5045:49;5041:119;;;5121:24;;;;;3773:42:40;3761:55;;5121:24:36;;;3743:74:40;3716:18;;5121:24:36;3597:226:40;5041:119:36;-1:-1:-1;5180:10:36;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:40:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:40;238:16;;231:27;14:250::o;269:330::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;513:2;501:15;518:66;497:88;488:98;;;;588:4;484:109;;269:330;-1:-1:-1;;269:330:40:o;604:220::-;753:2;742:9;735:21;716:4;773:45;814:2;803:9;799:18;791:6;773:45;:::i;829:154::-;915:42;908:5;904:54;897:5;894:65;884:93;;973:1;970;963:12;988:367;1056:6;1064;1117:2;1105:9;1096:7;1092:23;1088:32;1085:52;;;1133:1;1130;1123:12;1085:52;1172:9;1159:23;1191:31;1216:5;1191:31;:::i;:::-;1241:5;1319:2;1304:18;;;;1291:32;;-1:-1:-1;;;988:367:40:o;1552:158::-;1614:5;1659:3;1650:6;1645:3;1641:16;1637:26;1634:46;;;1676:1;1673;1666:12;1634:46;-1:-1:-1;1698:6:40;1552:158;-1:-1:-1;1552:158:40:o;1715:360::-;1803:6;1856:2;1844:9;1835:7;1831:23;1827:32;1824:52;;;1872:1;1869;1862:12;1824:52;1912:9;1899:23;1945:18;1937:6;1934:30;1931:50;;;1977:1;1974;1967:12;1931:50;2000:69;2061:7;2052:6;2041:9;2037:22;2000:69;:::i;2234:1358::-;2154:12;;2142:25;;2216:4;2205:16;;;2199:23;2183:14;;;2176:47;2600:4;2648:3;2633:19;;2742:3;2737:2;2726:9;2722:18;2715:31;2766:6;2801;2795:13;2832:6;2824;2817:22;2870:3;2859:9;2855:19;2848:26;;2933:3;2923:6;2920:1;2916:14;2905:9;2901:30;2897:40;2883:54;;2972:4;2964:6;2960:17;2995:1;3005:495;3019:6;3016:1;3013:13;3005:495;;;3108:66;3096:9;3088:6;3084:22;3080:95;3075:3;3068:108;3205:6;3199:13;3246:2;3240:9;3232:6;3225:25;3297:4;3293:2;3289:13;3283:20;3263:40;;3342:2;3335:4;3327:6;3323:17;3316:29;3368:48;3412:2;3404:6;3400:15;3386:12;3368:48;:::i;:::-;3358:58;-1:-1:-1;;3451:4:40;3476:14;;;;3439:17;;;;;3041:1;3034:9;3005:495;;;-1:-1:-1;;2154:12:40;;3582:2;3567:18;;2142:25;-1:-1:-1;;2216:4:40;2205:16;;2199:23;2183:14;;;2176:47;3517:6;-1:-1:-1;3532:54:40;2080:149;3828:154;3887:5;3932:2;3923:6;3918:3;3914:16;3910:25;3907:45;;;3948:1;3945;3938:12;3987:347;4038:8;4048:6;4102:3;4095:4;4087:6;4083:17;4079:27;4069:55;;4120:1;4117;4110:12;4069:55;-1:-1:-1;4143:20:40;;4186:18;4175:30;;4172:50;;;4218:1;4215;4208:12;4172:50;4255:4;4247:6;4243:17;4231:29;;4307:3;4300:4;4291:6;4283;4279:19;4275:30;4272:39;4269:59;;;4324:1;4321;4314:12;4269:59;3987:347;;;;;:::o;4339:1093::-;4480:6;4488;4496;4504;4512;4520;4528;4581:3;4569:9;4560:7;4556:23;4552:33;4549:53;;;4598:1;4595;4588:12;4549:53;4621;4666:7;4655:9;4621:53;:::i;:::-;4611:63;-1:-1:-1;4743:2:40;4728:18;;4715:32;;-1:-1:-1;4822:3:40;4807:19;;4794:33;4850:18;4839:30;;4836:50;;;4882:1;4879;4872:12;4836:50;4921:58;4971:7;4962:6;4951:9;4947:22;4921:58;:::i;:::-;4998:8;;-1:-1:-1;4895:84:40;-1:-1:-1;;5085:3:40;5070:19;;5057:33;5099;5057;5099;:::i;:::-;5151:7;-1:-1:-1;5211:3:40;5196:19;;5183:33;5241:18;5228:32;;5225:52;;;5273:1;5270;5263:12;5225:52;5312:60;5364:7;5353:8;5342:9;5338:24;5312:60;:::i;:::-;4339:1093;;;;-1:-1:-1;4339:1093:40;;-1:-1:-1;4339:1093:40;;;;5286:86;;-1:-1:-1;;;4339:1093:40:o;6458:508::-;6535:6;6543;6551;6604:2;6592:9;6583:7;6579:23;6575:32;6572:52;;;6620:1;6617;6610:12;6572:52;6659:9;6646:23;6678:31;6703:5;6678:31;:::i;:::-;6728:5;-1:-1:-1;6785:2:40;6770:18;;6757:32;6798:33;6757:32;6798:33;:::i;:::-;6458:508;;6850:7;;-1:-1:-1;;;6930:2:40;6915:18;;;;6902:32;;6458:508::o;7160:163::-;7227:20;;7287:10;7276:22;;7266:33;;7256:61;;7313:1;7310;7303:12;7256:61;7160:163;;;:::o;7328:298::-;7395:6;7403;7456:2;7444:9;7435:7;7431:23;7427:32;7424:52;;;7472:1;7469;7462:12;7424:52;7495:28;7513:9;7495:28;:::i;7631:118::-;7717:5;7710:13;7703:21;7696:5;7693:32;7683:60;;7739:1;7736;7729:12;7754:489;7848:6;7856;7909:2;7897:9;7888:7;7884:23;7880:32;7877:52;;;7925:1;7922;7915:12;7877:52;7965:9;7952:23;7998:18;7990:6;7987:30;7984:50;;;8030:1;8027;8020:12;7984:50;8053:69;8114:7;8105:6;8094:9;8090:22;8053:69;:::i;:::-;8043:79;;;8172:2;8161:9;8157:18;8144:32;8185:28;8207:5;8185:28;:::i;:::-;8232:5;8222:15;;;7754:489;;;;;:::o;8248:253::-;2154:12;;2142:25;;2216:4;2205:16;;;2199:23;2183:14;;;2176:47;8438:2;8423:18;;8450:45;2080:149;8506:159;8573:20;;8633:6;8622:18;;8612:29;;8602:57;;8655:1;8652;8645:12;8670:256;8736:6;8744;8797:2;8785:9;8776:7;8772:23;8768:32;8765:52;;;8813:1;8810;8803:12;8765:52;8836:28;8854:9;8836:28;:::i;:::-;8826:38;;8883:37;8916:2;8905:9;8901:18;8883:37;:::i;:::-;8873:47;;8670:256;;;;;:::o;9413:247::-;9472:6;9525:2;9513:9;9504:7;9500:23;9496:32;9493:52;;;9541:1;9538;9531:12;9493:52;9580:9;9567:23;9599:31;9624:5;9599:31;:::i;9870:668::-;9982:6;9990;9998;10006;10059:3;10047:9;10038:7;10034:23;10030:33;10027:53;;;10076:1;10073;10066:12;10027:53;10099;10144:7;10133:9;10099:53;:::i;:::-;10089:63;;10203:2;10192:9;10188:18;10175:32;10230:18;10222:6;10219:30;10216:50;;;10262:1;10259;10252:12;10216:50;10301:58;10351:7;10342:6;10331:9;10327:22;10301:58;:::i;:::-;10378:8;;-1:-1:-1;10275:84:40;-1:-1:-1;;10463:3:40;10448:19;;10435:33;10477:31;10435:33;10477:31;:::i;:::-;9870:668;;;;-1:-1:-1;9870:668:40;;-1:-1:-1;;9870:668:40:o;10543:395::-;10634:8;10644:6;10698:3;10691:4;10683:6;10679:17;10675:27;10665:55;;10716:1;10713;10706:12;10665:55;-1:-1:-1;10739:20:40;;10782:18;10771:30;;10768:50;;;10814:1;10811;10804:12;10768:50;10851:4;10843:6;10839:17;10827:29;;10911:3;10904:4;10894:6;10891:1;10887:14;10879:6;10875:27;10871:38;10868:47;10865:67;;;10928:1;10925;10918:12;10943:504;11068:6;11076;11129:2;11117:9;11108:7;11104:23;11100:32;11097:52;;;11145:1;11142;11135:12;11097:52;11185:9;11172:23;11218:18;11210:6;11207:30;11204:50;;;11250:1;11247;11240:12;11204:50;11289:98;11379:7;11370:6;11359:9;11355:22;11289:98;:::i;:::-;11406:8;;11263:124;;-1:-1:-1;10943:504:40;-1:-1:-1;;;;10943:504:40:o;11452:184::-;11510:6;11563:2;11551:9;11542:7;11538:23;11534:32;11531:52;;;11579:1;11576;11569:12;11531:52;11602:28;11620:9;11602:28;:::i;11823:553::-;11909:6;11917;11925;11933;11986:2;11974:9;11965:7;11961:23;11957:32;11954:52;;;12002:1;11999;11992:12;11954:52;12025:28;12043:9;12025:28;:::i;:::-;12015:38;;12072:37;12105:2;12094:9;12090:18;12072:37;:::i;:::-;12062:47;;12160:2;12149:9;12145:18;12132:32;12187:18;12179:6;12176:30;12173:50;;;12219:1;12216;12209:12;12173:50;12258:58;12308:7;12299:6;12288:9;12284:22;12258:58;:::i;:::-;11823:553;;;;-1:-1:-1;12335:8:40;-1:-1:-1;;;;11823:553:40:o;12884:714::-;13020:6;13028;13036;13080:9;13071:7;13067:23;13110:3;13106:2;13102:12;13099:32;;;13127:1;13124;13117:12;13099:32;13167:9;13154:23;13200:18;13192:6;13189:30;13186:50;;;13232:1;13229;13222:12;13186:50;13255:69;13316:7;13307:6;13296:9;13292:22;13255:69;:::i;:::-;13245:79;;;13417:2;13348:66;13344:2;13340:75;13336:84;13333:104;;;13433:1;13430;13423:12;13333:104;;13471:2;13460:9;13456:18;13446:28;;13524:2;13513:9;13509:18;13496:32;13537:31;13562:5;13537:31;:::i;:::-;13587:5;13577:15;;;12884:714;;;;;:::o;13603:609::-;13843:4;13885:3;13874:9;13870:19;13862:27;;13922:6;13916:13;13905:9;13898:32;13998:18;13990:4;13982:6;13978:17;13972:24;13968:49;13961:4;13950:9;13946:20;13939:79;14065:4;14057:6;14053:17;14047:24;14080:62;14136:4;14125:9;14121:20;14107:12;2154;;2142:25;;2216:4;2205:16;;;2199:23;2183:14;;2176:47;2080:149;14080:62;-1:-1:-1;2154:12:40;;14201:3;14186:19;;2142:25;2216:4;2205:16;;2199:23;2183:14;;;2176:47;14151:55;2080:149;14217:388;14285:6;14293;14346:2;14334:9;14325:7;14321:23;14317:32;14314:52;;;14362:1;14359;14352:12;14314:52;14401:9;14388:23;14420:31;14445:5;14420:31;:::i;:::-;14470:5;-1:-1:-1;14527:2:40;14512:18;;14499:32;14540:33;14499:32;14540:33;:::i;14610:234::-;14693:6;14746:2;14734:9;14725:7;14721:23;14717:32;14714:52;;;14762:1;14759;14752:12;14714:52;14785:53;14830:7;14819:9;14785:53;:::i;14849:437::-;14928:1;14924:12;;;;14971;;;14992:61;;15046:4;15038:6;15034:17;15024:27;;14992:61;15099:2;15091:6;15088:14;15068:18;15065:38;15062:218;;15136:77;15133:1;15126:88;15237:4;15234:1;15227:15;15265:4;15262:1;15255:15;15291:184;15343:77;15340:1;15333:88;15440:4;15437:1;15430:15;15464:4;15461:1;15454:15;15748:253;15820:2;15814:9;15862:4;15850:17;;15897:18;15882:34;;15918:22;;;15879:62;15876:88;;;15944:18;;:::i;:::-;15980:2;15973:22;15748:253;:::o;16006:251::-;16078:2;16072:9;;;16108:15;;16153:18;16138:34;;16174:22;;;16135:62;16132:88;;;16200:18;;:::i;16262:334::-;16333:2;16327:9;16389:2;16379:13;;16394:66;16375:86;16363:99;;16492:18;16477:34;;16513:22;;;16474:62;16471:88;;;16539:18;;:::i;:::-;16575:2;16568:22;16262:334;;-1:-1:-1;16262:334:40:o;16601:245::-;16649:4;16682:18;16674:6;16671:30;16668:56;;;16704:18;;:::i;:::-;-1:-1:-1;16761:2:40;16749:15;16766:66;16745:88;16835:4;16741:99;;16601:245::o;16851:1784::-;17043:9;17081:18;17073:6;17070:30;17067:56;;;17103:18;;:::i;:::-;17149:6;17146:1;17142:14;17176:30;17200:4;17196:2;17192:13;17176:30;:::i;:::-;17240:19;;;17312:14;;;;17284:4;17275:14;;;17349;17338:26;;17335:46;;;17377:1;17374;17367:12;17335:46;17401:5;17415:1187;17431:6;17426:3;17423:15;17415:1187;;;17519:3;17506:17;17555:18;17542:11;17539:35;17536:55;;;17587:1;17584;17577:12;17536:55;17614:23;;17682:4;17661:14;17657:23;;;17653:34;17650:54;;;17700:1;17697;17690:12;17650:54;17732:22;;:::i;:::-;17783:21;17801:2;17783:21;:::i;:::-;17774:7;17767:38;17845:32;17871:4;17867:2;17863:13;17845:32;:::i;:::-;17838:4;17829:7;17825:18;17818:60;17926:2;17922;17918:11;17905:25;17957:18;17949:6;17946:30;17943:50;;;17989:1;17986;17979:12;17943:50;18016:15;;;;;18073:14;18066:4;18058:13;;18054:34;18044:62;;18102:1;18099;18092:12;18044:62;18148:2;18135:16;18179:54;18195:37;18223:8;18195:37;:::i;:::-;18179:54;:::i;:::-;18262:8;18253:7;18246:25;18320:14;18313:4;18302:8;18298:2;18294:17;18290:28;18287:48;18284:68;;;18348:1;18345;18338:12;18284:68;18413:8;18406:4;18402:2;18398:13;18391:4;18382:7;18378:18;18365:57;18477:1;18470:4;18459:8;18450:7;18446:22;18442:33;18435:44;18517:7;18512:2;18503:7;18499:16;18492:33;;;18550:7;18545:3;18538:20;;;18587:4;18582:3;18578:14;18571:21;;17457:4;17452:3;17448:14;17441:21;;17415:1187;;;-1:-1:-1;18624:5:40;16851:1784;-1:-1:-1;;;;;16851:1784:40:o;18640:331::-;18745:9;18756;18798:8;18786:10;18783:24;18780:44;;;18820:1;18817;18810:12;18780:44;18849:6;18839:8;18836:20;18833:40;;;18869:1;18866;18859:12;18833:40;-1:-1:-1;;18895:23:40;;;18940:25;;;;;-1:-1:-1;18640:331:40:o;18976:476::-;19167:3;19205:6;19199:13;19221:66;19280:6;19275:3;19268:4;19260:6;19256:17;19221:66;:::i;:::-;19309:16;;19362:6;19354;19309:16;19334:35;19426:1;19388:18;;19415:13;;;-1:-1:-1;19388:18:40;;18976:476;-1:-1:-1;;;18976:476:40:o;19457:325::-;19545:6;19540:3;19533:19;19597:6;19590:5;19583:4;19578:3;19574:14;19561:43;;19649:1;19642:4;19633:6;19628:3;19624:16;19620:27;19613:38;19515:3;19771:4;19701:66;19696:2;19688:6;19684:15;19680:88;19675:3;19671:98;19667:109;19660:116;;19457:325;;;;:::o;19787:244::-;19944:2;19933:9;19926:21;19907:4;19964:61;20021:2;20010:9;20006:18;19998:6;19990;19964:61;:::i;20036:184::-;20088:77;20085:1;20078:88;20185:4;20182:1;20175:15;20209:4;20206:1;20199:15;20225:389;20324:4;20382:11;20369:25;20472:66;20461:8;20445:14;20441:29;20437:102;20417:18;20413:127;20403:155;;20554:1;20551;20544:12;20403:155;20575:33;;;;;20225:389;-1:-1:-1;;20225:389:40:o;20619:580::-;20696:4;20702:6;20762:11;20749:25;20852:66;20841:8;20825:14;20821:29;20817:102;20797:18;20793:127;20783:155;;20934:1;20931;20924:12;20783:155;20961:33;;21013:20;;;-1:-1:-1;21056:18:40;21045:30;;21042:50;;;21088:1;21085;21078:12;21042:50;21121:4;21109:17;;-1:-1:-1;21152:14:40;21148:27;;;21138:38;;21135:58;;;21189:1;21186;21179:12;21204:129;21289:18;21282:5;21278:30;21271:5;21268:41;21258:69;;21323:1;21320;21313:12;21338:1063;21712:10;21685:25;21703:6;21685:25;:::i;:::-;21681:42;21663:61;;21790:4;21778:17;;;21765:31;21812:20;;;21805:35;21644:4;21889;21877:17;;21864:31;21904:32;21864:31;21904:32;:::i;:::-;21987:18;21978:7;21974:32;21967:4;21956:9;21952:20;21945:62;;22043:6;22038:2;22027:9;22023:18;22016:34;22087:3;22081;22070:9;22066:19;22059:32;22114:62;22171:3;22160:9;22156:19;22148:6;22140;22114:62;:::i;:::-;22225:42;22217:6;22213:55;22207:3;22196:9;22192:19;22185:84;22318:9;22310:6;22306:22;22300:3;22289:9;22285:19;22278:51;22346:49;22388:6;22380;22372;22346:49;:::i;:::-;22338:57;21338:1063;-1:-1:-1;;;;;;;;;;21338:1063:40:o;22406:667::-;22485:6;22538:2;22526:9;22517:7;22513:23;22509:32;22506:52;;;22554:1;22551;22544:12;22506:52;22587:9;22581:16;22620:18;22612:6;22609:30;22606:50;;;22652:1;22649;22642:12;22606:50;22675:22;;22728:4;22720:13;;22716:27;-1:-1:-1;22706:55:40;;22757:1;22754;22747:12;22706:55;22790:2;22784:9;22815:52;22831:35;22859:6;22831:35;:::i;22815:52::-;22890:6;22883:5;22876:21;22938:7;22933:2;22924:6;22920:2;22916:15;22912:24;22909:37;22906:57;;;22959:1;22956;22949:12;22906:57;22972:71;23036:6;23031:2;23024:5;23020:14;23015:2;23011;23007:11;22972:71;:::i;23078:487::-;23165:6;23225:2;23213:9;23204:7;23200:23;23196:32;23240:2;23237:22;;;23255:1;23252;23245:12;23237:22;-1:-1:-1;23297:22:40;;:::i;:::-;23364:23;;23396:22;;23491:2;23476:18;;;23463:32;23511:14;;;23504:31;;;;-1:-1:-1;23403:5:40;23078:487;-1:-1:-1;23078:487:40:o;24359:245::-;24417:6;24470:2;24458:9;24449:7;24445:23;24441:32;24438:52;;;24486:1;24483;24476:12;24438:52;24525:9;24512:23;24544:30;24568:5;24544:30;:::i;24609:502::-;24859:42;24851:6;24847:55;24836:9;24829:74;24939:6;24934:2;24923:9;24919:18;24912:34;24994:6;24986;24982:19;24977:2;24966:9;24962:18;24955:47;25038:3;25033:2;25022:9;25018:18;25011:31;24810:4;25059:46;25100:3;25089:9;25085:19;25077:6;25059:46;:::i;25757:379::-;25950:2;25939:9;25932:21;25913:4;25976:45;26017:2;26006:9;26002:18;25994:6;25976:45;:::i;:::-;26069:9;26061:6;26057:22;26052:2;26041:9;26037:18;26030:50;26097:33;26123:6;26115;26097:33;:::i;26141:245::-;26208:6;26261:2;26249:9;26240:7;26236:23;26232:32;26229:52;;;26277:1;26274;26267:12;26229:52;26309:9;26303:16;26328:28;26350:5;26328:28;:::i;26391:969::-;26610:2;26599:9;26592:21;26668:10;26659:6;26653:13;26649:30;26644:2;26633:9;26629:18;26622:58;26734:4;26726:6;26722:17;26716:24;26711:2;26700:9;26696:18;26689:52;26573:4;26788:2;26780:6;26776:15;26770:22;26829:4;26823:3;26812:9;26808:19;26801:33;26857:52;26904:3;26893:9;26889:19;26875:12;26857:52;:::i;:::-;26843:66;;26958:2;26950:6;26946:15;26940:22;27028:66;27016:9;27008:6;27004:22;27000:95;26993:4;26982:9;26978:20;26971:125;27119:41;27153:6;27137:14;27119:41;:::i;:::-;27229:3;27217:16;;;;27211:23;27204:31;27197:39;27191:3;27176:19;;27169:68;-1:-1:-1;;;27310:42:40;27298:55;;;;27291:4;27276:20;;;27269:85;27105:55;26391:969::o;27365:388::-;27435:5;27483:4;27471:9;27466:3;27462:19;27458:30;27455:50;;;27501:1;27498;27491:12;27455:50;27523:22;;:::i;:::-;27590:16;;27615:22;;27703:2;27688:18;;;27682:25;27723:14;;;27716:31;;;;-1:-1:-1;27514:31:40;27365:388;-1:-1:-1;27365:388:40:o;27758:257::-;27856:6;27909:2;27897:9;27888:7;27884:23;27880:32;27877:52;;;27925:1;27922;27915:12;27877:52;27948:61;28001:7;27990:9;27948:61;:::i;28145:517::-;28246:2;28241:3;28238:11;28235:421;;;28282:5;28279:1;28272:16;28326:4;28323:1;28313:18;28396:2;28384:10;28380:19;28377:1;28373:27;28367:4;28363:38;28432:4;28420:10;28417:20;28414:47;;;-1:-1:-1;28455:4:40;28414:47;28510:2;28505:3;28501:12;28498:1;28494:20;28488:4;28484:31;28474:41;;28565:81;28583:2;28576:5;28573:13;28565:81;;;28642:1;28628:16;;28609:1;28598:13;28565:81;;28898:1414;29022:3;29016:10;29049:18;29041:6;29038:30;29035:56;;;29071:18;;:::i;:::-;29100:96;29189:6;29149:38;29181:4;29175:11;29149:38;:::i;:::-;29143:4;29100:96;:::i;:::-;29245:4;29276:2;29265:14;;29293:1;29288:767;;;;30099:1;30116:6;30113:89;;;-1:-1:-1;30168:19:40;;;30162:26;30113:89;28804:66;28795:1;28791:11;;;28787:84;28783:89;28773:100;28879:1;28875:11;;;28770:117;30215:81;;29258:1048;;29288:767;28092:1;28085:14;;;28129:4;28116:18;;29336:66;29324:79;;;29500:222;29514:7;29511:1;29508:14;29500:222;;;29596:19;;;29590:26;29575:42;;29703:4;29688:20;;;;29656:1;29644:14;;;;29530:12;29500:222;;;29504:3;29750:6;29741:7;29738:19;29735:261;;;29811:19;;;29805:26;29912:66;29894:1;29890:14;;;29906:3;29886:24;29882:97;29878:102;29863:118;29848:134;;29735:261;-1:-1:-1;;;;30042:1:40;30026:14;;;30022:22;30009:36;;-1:-1:-1;28898:1414:40:o;30317:1158::-;30533:4;30581:2;30570:9;30566:18;30611:2;30600:9;30593:21;30634:6;30669;30663:13;30700:6;30692;30685:22;30738:2;30727:9;30723:18;30716:25;;30800:2;30790:6;30787:1;30783:14;30772:9;30768:30;30764:39;30750:53;;30838:2;30830:6;30826:15;30859:1;30869:577;30883:6;30880:1;30877:13;30869:577;;;30972:66;30960:9;30952:6;30948:22;30944:95;30939:3;30932:108;31069:6;31063:13;31119:10;31114:2;31108:9;31104:26;31096:6;31089:42;31192:6;31186:2;31182;31178:11;31172:18;31168:31;31163:2;31155:6;31151:15;31144:56;31247:2;31243;31239:11;31233:18;31213:38;;31288:4;31283:2;31275:6;31271:15;31264:29;31316:50;31360:4;31352:6;31348:17;31334:12;31316:50;:::i;:::-;31306:60;-1:-1:-1;;31401:2:40;31424:12;;;;31389:15;;;;;30905:1;30898:9;30869:577;;;-1:-1:-1;31463:6:40;;30317:1158;-1:-1:-1;;;;;;30317:1158:40:o;31480:560::-;31582:6;31642:3;31630:9;31621:7;31617:23;31613:33;31658:2;31655:22;;;31673:1;31670;31663:12;31655:22;-1:-1:-1;31715:22:40;;:::i;:::-;31766:9;31760:16;31753:5;31746:31;31822:2;31811:9;31807:18;31801:25;31835:32;31859:7;31835:32;:::i;:::-;31894:2;31883:14;;31876:31;31939:70;32001:7;31996:2;31981:18;;31939:70;:::i;:::-;31934:2;31923:14;;31916:94;31927:5;31480:560;-1:-1:-1;;;31480:560:40:o;32045:184::-;32097:77;32094:1;32087:88;32194:4;32191:1;32184:15;32218:4;32215:1;32208:15;32234:274;32274:1;32300;32290:189;;32335:77;32332:1;32325:88;32436:4;32433:1;32426:15;32464:4;32461:1;32454:15;32290:189;-1:-1:-1;32493:9:40;;32234:274::o;32513:168::-;32586:9;;;32617;;32634:15;;;32628:22;;32614:37;32604:71;;32655:18;;:::i;32686:315::-;32806:19;;32845:2;32837:11;;32834:161;;;32917:66;32906:2;32902:12;;;32899:1;32895:20;32891:93;32880:105;32686:315;;;;:::o;33006:476::-;33126:19;;33171:66;33163:75;;;33258:1;33250:10;;33247:229;;;33399:66;33329;33322:3;33319:1;33315:11;33312:1;33308:19;33304:92;33300:2;33296:101;33292:174;33283:183;;33247:229;;33006:476;;;;:::o;33487:652::-;33748:66;33739:6;33734:3;33730:16;33726:89;33721:3;33714:102;33867:66;33858:6;33853:3;33849:16;33845:89;33841:1;33836:3;33832:11;33825:110;33965:6;33960:2;33955:3;33951:12;33944:28;33696:3;34001:6;33995:13;34017:75;34085:6;34080:2;34075:3;34071:12;34064:4;34056:6;34052:17;34017:75;:::i;:::-;34112:16;;;;34130:2;34108:25;;33487:652;-1:-1:-1;;;;;33487:652:40:o;34144:125::-;34209:9;;;34230:10;;;34227:36;;;34243:18;;:::i;34607:570::-;34848:6;34843:3;34836:19;34907:66;34898:6;34893:3;34889:16;34885:89;34880:2;34875:3;34871:12;34864:111;35005:6;35000:2;34995:3;34991:12;34984:28;34818:3;35041:6;35035:13;35057:73;35123:6;35118:2;35113:3;35109:12;35104:2;35096:6;35092:15;35057:73;:::i;:::-;35150:16;;;;35168:2;35146:25;;34607:570;-1:-1:-1;;;;;34607:570:40:o;35182:251::-;35252:6;35305:2;35293:9;35284:7;35280:23;35276:32;35273:52;;;35321:1;35318;35311:12;35273:52;35353:9;35347:16;35372:31;35397:5;35372:31;:::i;35860:287::-;35989:3;36027:6;36021:13;36043:66;36102:6;36097:3;36090:4;36082:6;36078:17;36043:66;:::i

Swarm Source

ipfs://d1c3f6c95e50de22b49ba7fe41b6d9d8c06fd27b8cbb411cf42a9ed68ee74d82
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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