Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
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)
Balance
0.000000000034405613 razValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
RazOFTNoTax
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity Standard Json-Input format)
// 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) {} }
// 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); } }
// 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; } }
// 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; } }
// 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; } }
// 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); } } } }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); } }
// 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); } }
// 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); }
// 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); }
// 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); }
// 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))); } }
// 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))); } }
// 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); } }
// 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; }
// 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); } }
// 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); }
// 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); }
// 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); }
// 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; } }
// 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; }
// 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); }
// 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; }
// 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]; } } }
// 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); }
// 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(); } } }
// 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); }
// 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; }
// 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); }
// 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); }
// 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; }
// 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)); } }
// 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; }
// 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)); } }
// 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); }
// 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); }
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.