Source Code
Overview
MON Balance
MON Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
BridgeableReceiptToken
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity)
/**
*Submitted for verification at monadscan.com on 2025-12-10
*/
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0 ^0.8.0 ^0.8.20;
// lib/layer-zero/lz-evm-protocol-v2/contracts/libs/AddressCast.sol
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));
}
}
// src/core/BaseReentrancy.sol
abstract contract BaseReentrancy {
// ----------------------------------------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------------------------------------
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
// ----------------------------------------------------------------------------------------------------
// Errors
// ----------------------------------------------------------------------------------------------------
error ReentrantCall();
// ----------------------------------------------------------------------------------------------------
// Storage layout
// ----------------------------------------------------------------------------------------------------
uint256 private _status;
// ----------------------------------------------------------------------------------------------------
// Modifiers
// ----------------------------------------------------------------------------------------------------
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == _ENTERED) {
revert ReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
// node_modules/@openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// src/core/interfaces/IConfigurableMintableToken.sol
interface IConfigurableMintableToken {
function configure(address[] calldata newMinters, address[] calldata newBurners) external;
}
// node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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);
}
// node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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);
}
// lib/openzeppelin-contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20PermitUpgradeable {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// lib/openzeppelin-contracts-upgradeable/interfaces/IERC5267Upgradeable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)
interface IERC5267Upgradeable {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol
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 _timeout) 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 _gracePeriod) 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);
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol
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);
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol
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;
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}
// src/core/interfaces/IMintableBurnable.sol
interface IMintableBurnable {
/**
* @notice Issues a given amount of tokens to the address specified.
* @param addr The address of the receiver.
* @param amount The number of tokens to issue.
*/
function mint(address addr, uint256 amount) external;
/**
* @notice Burns tokens from the address specified.
* @param addr The token holder.
* @param amount The number of tokens to burn.
*/
function burn(address addr, uint256 amount) external;
}
// lib/layer-zero/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol
/**
* @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);
}
// lib/layer-zero/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol
/**
* @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);
}
// lib/layer-zero/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol
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);
}
// node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reinitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
*
* NOTE: Consider following the ERC-7201 formula to derive storage locations.
*/
function _initializableStorageSlot() internal pure virtual returns (bytes32) {
return INITIALIZABLE_STORAGE;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
bytes32 slot = _initializableStorageSlot();
assembly {
$.slot := slot
}
}
}
// lib/layer-zero/oft-evm/contracts/libs/OFTComposeMsgCodec.sol
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)));
}
}
// lib/layer-zero/oft-evm/contracts/libs/OFTMsgCodec.sol
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)));
}
}
// node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 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 ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-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 ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 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);
}
// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
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;
}
}
// node_modules/@openzeppelin/contracts/interfaces/IERC165.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
// node_modules/@openzeppelin/contracts/interfaces/IERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
// node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
/**
* @dev Interface for the optional metadata functions from the ERC-20 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);
}
// node_modules/@openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* 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);
}
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.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);
}
// node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* 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 OwnableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @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.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
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) {
OwnableStorage storage $ = _getOwnableStorage();
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 {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.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;
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/oapp/libs/OAppOptionsType3Upgradeable.sol
/**
* @title OAppOptionsType3
* @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
*/
abstract contract OAppOptionsType3Upgradeable is IOAppOptionsType3, OwnableUpgradeable {
struct OAppOptionsType3Storage {
// @dev The "msgType" should be defined in the child contract.
mapping(uint32 => mapping(uint16 => bytes)) enforcedOptions;
}
// keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappoptionstype3")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION =
0x8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea0000;
uint16 internal constant OPTION_TYPE_3 = 3;
function _getOAppOptionsType3Storage() internal pure returns (OAppOptionsType3Storage storage $) {
assembly {
$.slot := OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION
}
}
/**
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OAppOptionsType3_init() internal onlyInitializing {}
function __OAppOptionsType3_init_unchained() internal onlyInitializing {}
function enforcedOptions(uint32 _eid, uint16 _msgType) public view returns (bytes memory) {
OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
return $.enforcedOptions[_eid][_msgType];
}
/**
* @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 {
OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
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) {
OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage();
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 calldata _options) internal pure virtual {
uint16 optionsType = uint16(bytes2(_options[0:2]));
if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
}
}
// node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.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 ERC-20
* applications.
*/
abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
/// @custom:storage-location erc7201:openzeppelin.storage.ERC20
struct ERC20Storage {
mapping(address account => uint256) _balances;
mapping(address account => mapping(address spender => uint256)) _allowances;
uint256 _totalSupply;
string _name;
string _symbol;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
function _getERC20Storage() private pure returns (ERC20Storage storage $) {
assembly {
$.slot := ERC20StorageLocation
}
}
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
ERC20Storage storage $ = _getERC20Storage();
$._name = name_;
$._symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
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) {
ERC20Storage storage $ = _getERC20Storage();
return $._totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
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) {
ERC20Storage storage $ = _getERC20Storage();
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}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* 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 {
ERC20Storage storage $ = _getERC20Storage();
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:
*
* ```solidity
* 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 {
ERC20Storage storage $ = _getERC20Storage();
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);
}
}
}
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.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;
}
// lib/layer-zero/oapp-evm/contracts/oapp/interfaces/IOAppCore.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;
}
// node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
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 Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
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 silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}
// lib/layer-zero/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.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);
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/interfaces/ISendLib.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;
}
// lib/layer-zero/oapp-evm/contracts/oapp/OAppCore.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);
}
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/oapp/OAppCoreUpgradeable.sol
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCoreUpgradeable is IOAppCore, OwnableUpgradeable {
struct OAppCoreStorage {
mapping(uint32 => bytes32) peers;
}
// keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappcore")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OAPP_CORE_STORAGE_LOCATION =
0x72ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900;
function _getOAppCoreStorage() internal pure returns (OAppCoreStorage storage $) {
assembly {
$.slot := OAPP_CORE_STORAGE_LOCATION
}
}
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
*/
constructor(address _endpoint) {
endpoint = ILayerZeroEndpointV2(_endpoint);
}
/**
* @dev Initializes the OAppCore with the provided delegate.
* @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.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OAppCore_init(address _delegate) internal onlyInitializing {
__OAppCore_init_unchained(_delegate);
}
function __OAppCore_init_unchained(address _delegate) internal onlyInitializing {
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Returns the peer address (OApp instance) associated with a specific endpoint.
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function peers(uint32 _eid) public view override returns (bytes32) {
OAppCoreStorage storage $ = _getOAppCoreStorage();
return $.peers[_eid];
}
/**
* @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 {
OAppCoreStorage storage $ = _getOAppCoreStorage();
$.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) {
OAppCoreStorage storage $ = _getOAppCoreStorage();
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);
}
}
// lib/layer-zero/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.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));
}
}
// lib/layer-zero/oapp-evm/contracts/precrime/libs/Packet.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];
}
}
}
// lib/layer-zero/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol
// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
// solhint-disable-next-line no-unused-import
/**
* @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);
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/oapp/OAppReceiverUpgradeable.sol
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiverUpgradeable is IOAppReceiver, OAppCoreUpgradeable {
// 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;
/**
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OAppReceiver_init(address _delegate) internal onlyInitializing {
__OAppCore_init(_delegate);
}
function __OAppReceiver_init_unchained() internal onlyInitializing {}
/**
* @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;
}
// lib/layer-zero/oapp-evm/contracts/oapp/OAppSender.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);
}
}
// lib/layer-zero/oft-evm/contracts/interfaces/IOFT.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 the fee breakdown and settings data for an OFT. Unused in the default implementation.
* @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);
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/precrime/OAppPreCrimeSimulatorUpgradeable.sol
/**
* @title OAppPreCrimeSimulator
* @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
*/
abstract contract OAppPreCrimeSimulatorUpgradeable is IOAppPreCrimeSimulator, OwnableUpgradeable {
struct OAppPreCrimeSimulatorStorage {
// The address of the preCrime implementation.
address preCrime;
}
// keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappprecrimesimulator")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION =
0xefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600;
function _getOAppPreCrimeSimulatorStorage() internal pure returns (OAppPreCrimeSimulatorStorage storage $) {
assembly {
$.slot := OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION
}
}
/**
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OAppPreCrimeSimulator_init() internal onlyInitializing {}
function __OAppPreCrimeSimulator_init_unchained() internal onlyInitializing {}
function preCrime() external view override returns (address) {
OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage();
return $.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 {
OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage();
$.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);
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/oapp/OAppSenderUpgradeable.sol
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSenderUpgradeable is OAppCoreUpgradeable {
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;
/**
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OAppSender_init(address _delegate) internal onlyInitializing {
__OAppCore_init(_delegate);
}
function __OAppSender_init_unchained() internal onlyInitializing {}
/**
* @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);
}
}
// lib/layer-zero/oapp-evm-upgradeable/contracts/oapp/OAppUpgradeable.sol
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OAppUpgradeable is OAppSenderUpgradeable, OAppReceiverUpgradeable {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
*/
constructor(address _endpoint) OAppCoreUpgradeable(_endpoint) {}
/**
* @dev Initializes the OApp with the provided delegate.
* @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.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OApp_init(address _delegate) internal onlyInitializing {
__OAppCore_init(_delegate);
__OAppReceiver_init_unchained();
__OAppSender_init_unchained();
}
function __OApp_init_unchained() internal onlyInitializing {}
/**
* @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(OAppSenderUpgradeable, OAppReceiverUpgradeable)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}
// lib/layer-zero/oft-evm-upgradeable/contracts/oft-evm-upgradeable/OFTCoreUpgradeable.sol
/**
* @title OFTCore
* @dev Abstract contract for the OftChain (OFT) token.
*/
abstract contract OFTCoreUpgradeable is
IOFT,
OAppUpgradeable,
OAppPreCrimeSimulatorUpgradeable,
OAppOptionsType3Upgradeable
{
using OFTMsgCodec for bytes;
using OFTMsgCodec for bytes32;
struct OFTCoreStorage {
// Address of an optional contract to inspect both 'message' and 'options'
address msgInspector;
}
// keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftcore")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OFT_CORE_STORAGE_LOCATION =
0x41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c00;
// @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;
event MsgInspectorSet(address inspector);
function _getOFTCoreStorage() internal pure returns (OFTCoreStorage storage $) {
assembly {
$.slot := OFT_CORE_STORAGE_LOCATION
}
}
/**
* @dev Constructor.
* @param _localDecimals The decimals of the token on the local chain (this chain).
* @param _endpoint The address of the LayerZero endpoint.
*/
constructor(uint8 _localDecimals, address _endpoint) OAppUpgradeable(_endpoint) {
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 Initializes the OFTCore contract.
* @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.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OFTCore_init(address _delegate) internal onlyInitializing {
__OApp_init(_delegate);
__OAppPreCrimeSimulator_init();
__OAppOptionsType3_init();
}
function __OFTCore_init_unchained() internal onlyInitializing {}
function msgInspector() public view returns (address) {
OFTCoreStorage storage $ = _getOFTCoreStorage();
return $.msgInspector;
}
/**
* @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 pure 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 {
OFTCoreStorage storage $ = _getOFTCoreStorage();
$.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);
OFTCoreStorage storage $ = _getOFTCoreStorage();
// @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 from.
* @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);
}
// lib/layer-zero/oft-evm-upgradeable/contracts/oft-evm-upgradeable/OFTUpgradeable.sol
/**
* @title OFT Contract
* @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
*/
abstract contract OFTUpgradeable is OFTCoreUpgradeable, ERC20Upgradeable {
/**
* @dev Constructor for the OFT contract.
* @param _lzEndpoint The LayerZero endpoint address.
*/
constructor(address _lzEndpoint) OFTCoreUpgradeable(decimals(), _lzEndpoint) {}
/**
* @dev Initializes the OFT with the provided name, symbol, and delegate.
* @param _name The name of the OFT.
* @param _symbol The symbol of the OFT.
* @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.
* @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
* accommodate the different version of Ownable.
*/
function __OFT_init(string memory _name, string memory _symbol, address _delegate) internal onlyInitializing {
__ERC20_init(_name, _symbol);
__OFTCore_init(_delegate);
}
function __OFT_init_unchained() internal onlyInitializing {}
/**
* @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;
}
}
// src/core/BaseLayerZeroErc20.sol
/**
* @title Represents an upgradeable, bridgeable ERC-20.
* @dev The token is bridgeable via Layer Zero. The ownership model is a two-phase commit.
*/
abstract contract BaseLayerZeroErc20 is IERC5267Upgradeable, IERC20PermitUpgradeable, BaseReentrancy, OFTUpgradeable {
// -----------------------------------------------------------------------------------
// Errors
// -----------------------------------------------------------------------------------
error NotConfigured();
error AlreadyConfigured();
error Unauthorized();
error ZeroAddress();
error InvalidDomainSeparator();
error ExpiredDeadline();
error InvalidSigner();
error InvalidSignature();
error InvalidSignatureComponentS();
// -----------------------------------------------------------------------------------
// Constants
// -----------------------------------------------------------------------------------
bytes32 internal constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
/// @dev The default number of token decimals
uint8 internal constant _DEFAULT_TOKEN_DECIMALS = 18;
// -----------------------------------------------------------------------------------
// Storage layout
// -----------------------------------------------------------------------------------
string internal _domainName;
string internal _domainVersion;
bytes32 internal _domainSeparator;
/// @dev Indicates if the contract was configured
bool internal _configured;
/// @dev Decimal places of the ERC20
uint8 internal _tokenDecimals;
/// @dev The address of the pending owner, if any.
address private _pendingOwner;
mapping (address => uint256) internal _permitNonces;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[10] private __gap;
// -----------------------------------------------------------------------------------
// Events
// -----------------------------------------------------------------------------------
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
// -----------------------------------------------------------------------------------
// Modifiers
// -----------------------------------------------------------------------------------
modifier ifConfigured() {
if (!_configured) revert NotConfigured();
_;
}
modifier ifNotConfigured() {
if (_configured) revert AlreadyConfigured();
_;
}
constructor(address _lzEndpoint) OFTUpgradeable(_lzEndpoint) {}
/**
* @notice ERC20 Permit
*/
function permit(
address holderAddr,
address spenderAddr,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override nonReentrant {
if (deadline < block.timestamp) revert ExpiredDeadline();
// Forge the digest per EIP-712
bytes32 h = _toTypedDataHash(
_domainSeparator,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
holderAddr,
spenderAddr,
value,
_permitNonces[holderAddr],
deadline
)
)
);
// Attempt to recover the signature
address signer = _recover(h, v, r, s);
if (signer != holderAddr) revert InvalidSigner();
// Increment the nonce
_permitNonces[holderAddr]++;
// Run the ERC-20 approval
_approve(holderAddr, spenderAddr, value);
}
/**
* @notice Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* @dev Can only be called by the current owner.
* @param newOwner The address of the new owner.
*/
function transferOwnership(address newOwner) public virtual override nonReentrant ifConfigured onlyOwner {
if (newOwner == address(0)) revert ZeroAddress();
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @notice Accepts the ownership transfer initiated by the current owner of this contract.
*/
function acceptOwnership() public virtual nonReentrant ifConfigured {
if (_pendingOwner != msg.sender) revert Unauthorized();
_transferOwnership(msg.sender);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @notice Gets the address of the pending owner, if any.
* @return Returns the address of the pending owner. Returns the zero address if there is no pending owner at all.
*/
function pendingOwner() external view returns (address) {
return _pendingOwner;
}
/**
* @notice Gets the fields and values that describe the domain separator per ERC-5267.
*/
function eip712Domain() external view override returns (
bytes1 fields,
string memory domainName,
string memory domainVersion,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
) {
// Trigger a revert if the domain separator was not set
if (_domainSeparator == bytes32(0)) revert InvalidDomainSeparator();
return (
hex"0f", // 01111
_domainName,
_domainVersion,
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
/**
* @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 override returns (bytes32) {
return _domainSeparator;
}
function nonces(address addr) external view override returns (uint256) {
return _permitNonces[addr];
}
/**
* @notice Gets the number of token decimals across all chains.
* @return The number of token decimals, per ERC20.
*/
function decimals() public view virtual override returns (uint8) {
return (_tokenDecimals < uint8(1)) ? _DEFAULT_TOKEN_DECIMALS : _tokenDecimals;
}
function _recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert InvalidSignatureComponentS();
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) revert InvalidSignature();
return signer;
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function _toTypedDataHash(bytes32 targetDomainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), targetDomainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
}
// src/core/BridgeableReceiptToken.sol
/**
* @title Represents an upgradeable, bridgeable ERC-20.
* @dev The token is bridged via Layer Zero.
*/
contract BridgeableReceiptToken is IMintableBurnable, IConfigurableMintableToken, BaseLayerZeroErc20 {
error UnauthorizedMinter();
error UnauthorizedBurner();
error InvalidEpoch();
error TokensLocked();
error MissingLayerZeroEndpoint();
// --------------------------------------------------------------------------
// Storage layout
// --------------------------------------------------------------------------
/// @notice The addresses allowed to issue new tokens.
mapping (address => bool) public minters;
/// @notice The addresses allowed to burn existing tokens.
mapping (address => bool) public burners;
/// @dev The lock applied to a token holder, expressed as a Unix epoch
mapping (address => uint256) internal _lock;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[10] private __gap;
// --------------------------------------------------------------------------
// Events
// --------------------------------------------------------------------------
event OnTokensLocked(address holderAddr, uint256 untilEpoch);
event OnTokensUnLocked(address holderAddr);
// --------------------------------------------------------------------------
// Constructor
// --------------------------------------------------------------------------
constructor(address _lzEndpoint) BaseLayerZeroErc20(_lzEndpoint) {
_disableInitializers();
}
// --------------------------------------------------------------------------
// Modifiers
// --------------------------------------------------------------------------
/// @dev Throws if the sender is not a valid minter
modifier ifValidMinter() {
if (!minters[msg.sender]) revert UnauthorizedMinter();
_;
}
/// @dev Throws if the sender is not a valid burner
modifier ifValidBurner() {
if (!burners[msg.sender]) revert UnauthorizedBurner();
_;
}
/// @dev Throws if the tokens of the holder specified are locked.
modifier ifTokensNotLocked(address holderAddr) {
if (block.timestamp < _lock[holderAddr]) revert TokensLocked();
_;
}
// --------------------------------------------------------------------------
// Functions
// --------------------------------------------------------------------------
/**
* @notice Proxy initialization function.
* @param newOwnerAddr The owner of the token.
* @param erc20Decimals The token decimals.
* @param erc20Symbol The token symbol per ERC20.
* @param erc20Name The token name per ERC20.
*/
function initialize(
address newOwnerAddr,
uint8 erc20Decimals,
string memory erc20Symbol,
string memory erc20Name
) external virtual initializer {
if (address(endpoint) == address(0)) revert MissingLayerZeroEndpoint();
_domainName = erc20Name;
_domainVersion = "1";
_domainSeparator = keccak256(abi.encode(
_TYPE_HASH,
keccak256(bytes(_domainName)),
keccak256(bytes(_domainVersion)),
block.chainid,
address(this)
));
_tokenDecimals = erc20Decimals;
// Transfer the ownership directly. Bypass the two-step flow at initialization time
_transferOwnership(newOwnerAddr);
// Initialize the OFT
__OFT_init(erc20Name, erc20Symbol, newOwnerAddr);
}
/**
* @notice Configures the token.
* @param newMinters The addresses allowed to issue tokens.
* @param newBurners The addresses allowed to burn tokens.
*/
function configure(
address[] calldata newMinters,
address[] calldata newBurners
) external override nonReentrant ifNotConfigured onlyOwner {
_configured = true;
for (uint256 i; i < newMinters.length; i++) {
minters[newMinters[i]] = true;
}
for (uint256 i; i < newBurners.length; i++) {
burners[newBurners[i]] = true;
}
}
/**
* @notice Issues a given amount of tokens to the address specified.
* @param addr The address of the receiver.
* @param amount The number of tokens to issue.
*/
function mint(address addr, uint256 amount) external override nonReentrant ifConfigured ifValidMinter {
_mint(addr, amount);
}
/**
* @notice Burns tokens from the address specified.
* @param addr The token holder.
* @param amount The number of tokens to burn.
*/
function burn(address addr, uint256 amount) external override nonReentrant ifConfigured ifValidBurner {
_burn(addr, amount);
}
/**
* @notice Locks the tokens of the holder specified.
* @param holderAddr The address of the token holder.
* @param untilEpoch The end date of the lock.
*/
function lockTokens(
address holderAddr,
uint256 untilEpoch
) external virtual nonReentrant ifConfigured onlyOwner {
_lock[holderAddr] = untilEpoch + 15 minutes;
emit OnTokensLocked(holderAddr, untilEpoch);
}
/**
* @notice Unlocks the tokens of the holder specified.
* @param holderAddr The address of the token holder.
*/
function unlockTokens(address holderAddr) external virtual nonReentrant ifConfigured onlyOwner {
if (_lock[holderAddr] < 1) revert InvalidEpoch();
if (block.timestamp < _lock[holderAddr]) revert TokensLocked();
delete _lock[holderAddr];
emit OnTokensUnLocked(holderAddr);
}
// --------------------------------------------------------------------------
// ERC20 overrides
// --------------------------------------------------------------------------
function transfer(
address to,
uint256 amount
) public virtual override ifTokensNotLocked(msg.sender) returns (bool) {
return super.transfer(to, amount);
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override ifTokensNotLocked(from) returns (bool) {
return super.transferFrom(from, to, amount);
}
function approve(
address spender,
uint256 amount
) public virtual override ifTokensNotLocked(msg.sender) returns (bool) {
return super.approve(spender, amount);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_lzEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyConfigured","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":"ExpiredDeadline","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidDomainSeparator","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidEpoch","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureComponentS","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[],"name":"MissingLayerZeroEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[],"name":"NotConfigured","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[],"name":"NotInitializing","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":[],"name":"ReentrantCall","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"},{"inputs":[],"name":"TokensLocked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnauthorizedBurner","type":"error"},{"inputs":[],"name":"UnauthorizedMinter","type":"error"},{"inputs":[],"name":"ZeroAddress","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":[],"name":"EIP712DomainChanged","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":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":false,"internalType":"address","name":"holderAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"untilEpoch","type":"uint256"}],"name":"OnTokensLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"holderAddr","type":"address"}],"name":"OnTokensUnLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"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":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","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":"amount","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":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"burners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address[]","name":"newMinters","type":"address[]"},{"internalType":"address[]","name":"newBurners","type":"address[]"}],"name":"configure","outputs":[],"stateMutability":"nonpayable","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":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"domainName","type":"string"},{"internalType":"string","name":"domainVersion","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"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":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwnerAddr","type":"address"},{"internalType":"uint8","name":"erc20Decimals","type":"uint8"},{"internalType":"string","name":"erc20Symbol","type":"string"},{"internalType":"string","name":"erc20Name","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"holderAddr","type":"address"},{"internalType":"uint256","name":"untilEpoch","type":"uint256"}],"name":"lockTokens","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[{"internalType":"address","name":"addr","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holderAddr","type":"address"},{"internalType":"address","name":"spenderAddr","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","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":"pure","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":"amount","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":"amount","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"},{"inputs":[{"internalType":"address","name":"holderAddr","type":"address"}],"name":"unlockTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c060405234801561000f575f80fd5b5060405161485338038061485383398101604081905261002e91610189565b8080610038610098565b6001600160a01b03821660805281600660ff8316101561006b576040516301e9714b60e41b815260040160405180910390fd5b6100766006836101ca565b61008190600a6102c6565b60a052506100929250506100c29050565b506102d4565b6004545f90600161010090910460ff16106100bc5750600454610100900460ff1690565b50601290565b5f6100cb61015f565b805490915068010000000000000000900460ff16156100fd5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161461015c5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f60208284031215610199575f80fd5b81516001600160a01b03811681146101af575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b60ff8281168282160390811115610183576101836101b6565b6001815b600184111561021e57808504811115610202576102026101b6565b600184161561021057908102905b60019390931c9280026101e7565b935093915050565b5f8261023457506001610183565b8161024057505f610183565b816001811461025657600281146102605761027c565b6001915050610183565b60ff841115610271576102716101b6565b50506001821b610183565b5060208310610133831016604e8410600b841016171561029f575081810a610183565b6102ab5f1984846101e3565b805f19048211156102be576102be6101b6565b029392505050565b5f6101af60ff841683610226565b60805160a0516145116103425f395f818161087a01528181612a9401528181612b060152612c9e01525f81816106d201528181610d120152818161117a01528181611e370152818161243c015281816126b2015281816128e801528181612f68015261301f01526145115ff3fe608060405260043610610366575f3560e01c80637d25a05e116101c8578063bb0b6a53116100fd578063d42438851161009d578063f2fde38b1161006d578063f2fde38b14610a9f578063f46eccc414610abe578063fc0c546a1461064f578063ff7bd03d14610aec575f80fd5b8063d424388514610a1f578063d505accf14610a3e578063dd62ed3e14610a5d578063e30c397814610a7c575f80fd5b8063c7c7f5b3116100d8578063c7c7f5b3146109ad578063ca5eb5e1146109ce578063cb67f948146109ed578063d045a0dc14610a0c575f80fd5b8063bb0b6a531461093e578063bc70b3541461097b578063bd815db01461099a575f80fd5b8063963efcaa11610168578063a9059cbb11610143578063a9059cbb146108cd578063b1c25586146108ec578063b731ea0a1461090b578063b98bd0701461091f575f80fd5b8063963efcaa146108695780639dc29fac1461089c5780639f68b964146108bb575f80fd5b806384b0196e116101a357806384b0196e14610807578063857749b01461082e5780638da5cb5b1461084157806395d89b4114610855575f80fd5b80637d25a05e1461077b5780637ecebe00146107b457806382413eac146107e8575f80fd5b8063313ce5671161029e5780635535d4611161023e5780636fc1b31e116102195780636fc1b31e146106f457806370a0823114610713578063715018a61461075357806379ba509714610767575f80fd5b80635535d461146106615780635a0dfe4d146106805780635e280f11146106c1575f80fd5b80633b6f743b116102795780633b6f743b146105e557806340c10f191461061157806342fe09801461063057806352ae28791461064f575f80fd5b8063313ce5671461058c5780633400288b146105b25780633644e515146105d1575f80fd5b8063156a0d0f116103095780631f5e1334116102e45780631f5e13341461050757806323b872dd1461051b57806323ff63a61461053a57806330adf81f14610559575f80fd5b8063156a0d0f1461048357806317442b70146104a957806318160ddd146104ca575f80fd5b80630d35b415116103445780630d35b415146103ed578063111ecdad1461041b57806313137d6514610447578063134d4f251461045c575f80fd5b806303d41e0e1461036a57806306fdde03146103ad578063095ea7b3146103ce575b5f80fd5b348015610375575f80fd5b50610398610384366004613306565b60116020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103b8575f80fd5b506103c1610b0b565b6040516103a4919061334f565b3480156103d9575f80fd5b506103986103e8366004613361565b610bcb565b3480156103f8575f80fd5b5061040c6104073660046133a1565b610c11565b6040516103a4939291906133d2565b348015610426575f80fd5b5061042f610cdc565b6040516001600160a01b0390911681526020016103a4565b61045a6104553660046134c1565b610d10565b005b348015610467575f80fd5b50610470600281565b60405161ffff90911681526020016103a4565b34801561048e575f80fd5b506040805162b9270b60e21b815260016020820152016103a4565b3480156104b4575f80fd5b50604080516001815260026020820152016103a4565b3480156104d5575f80fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016103a4565b348015610512575f80fd5b50610470600181565b348015610526575f80fd5b5061039861053536600461355b565b610dd0565b348015610545575f80fd5b5061045a6105543660046135d9565b610e1e565b348015610564575f80fd5b506104f97f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b348015610597575f80fd5b506105a0610f53565b60405160ff90911681526020016103a4565b3480156105bd575f80fd5b5061045a6105cc36600461365b565b610f7d565b3480156105dc575f80fd5b506003546104f9565b3480156105f0575f80fd5b506106046105ff366004613682565b610fe8565b6040516103a491906136d0565b34801561061c575f80fd5b5061045a61062b366004613361565b61104e565b34801561063b575f80fd5b5061045a61064a3660046137db565b6110d8565b34801561065a575f80fd5b503061042f565b34801561066c575f80fd5b506103c161067b366004613871565b6112fc565b34801561068b575f80fd5b5061039861069a36600461365b565b63ffffffff919091165f9081525f805160206144bc83398151915260205260409020541490565b3480156106cc575f80fd5b5061042f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106ff575f80fd5b5061045a61070e366004613306565b6113d4565b34801561071e575f80fd5b506104f961072d366004613306565b6001600160a01b03165f9081525f8051602061449c833981519152602052604090205490565b34801561075e575f80fd5b5061045a611450565b348015610772575f80fd5b5061045a611463565b348015610786575f80fd5b5061079c61079536600461365b565b5f92915050565b6040516001600160401b0390911681526020016103a4565b3480156107bf575f80fd5b506104f96107ce366004613306565b6001600160a01b03165f9081526005602052604090205490565b3480156107f3575f80fd5b506103986108023660046138a2565b6114eb565b348015610812575f80fd5b5061081b611500565b6040516103a49796959493929190613904565b348015610839575f80fd5b5060066105a0565b34801561084c575f80fd5b5061042f61167a565b348015610860575f80fd5b506103c16116a2565b348015610874575f80fd5b506104f97f000000000000000000000000000000000000000000000000000000000000000081565b3480156108a7575f80fd5b5061045a6108b6366004613361565b6116e0565b3480156108c6575f80fd5b505f610398565b3480156108d8575f80fd5b506103986108e7366004613361565b611762565b3480156108f7575f80fd5b5061045a610906366004613361565b61179e565b348015610916575f80fd5b5061042f611858565b34801561092a575f80fd5b5061045a61093936600461399a565b611880565b348015610949575f80fd5b506104f96109583660046139d8565b63ffffffff165f9081525f805160206144bc833981519152602052604090205490565b348015610986575f80fd5b506103c16109953660046139f1565b6119fc565b61045a6109a836600461399a565b611b8c565b6109c06109bb366004613a41565b611d18565b6040516103a4929190613aa9565b3480156109d9575f80fd5b5061045a6109e8366004613306565b611e10565b3480156109f8575f80fd5b5061045a610a07366004613306565b611e91565b61045a610a1a3660046134c1565b611fa8565b348015610a2a575f80fd5b5061045a610a39366004613306565b611fd7565b348015610a49575f80fd5b5061045a610a58366004613afa565b61204b565b348015610a68575f80fd5b506104f9610a77366004613b64565b6121b6565b348015610a87575f80fd5b506004546201000090046001600160a01b031661042f565b348015610aaa575f80fd5b5061045a610ab9366004613306565b6121ff565b348015610ac9575f80fd5b50610398610ad8366004613306565b60106020525f908152604090205460ff1681565b348015610af7575f80fd5b50610398610b06366004613b90565b6122e3565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060915f8051602061449c83398151915291610b4990613baa565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7590613baa565b8015610bc05780601f10610b9757610100808354040283529160200191610bc0565b820191905f5260205f20905b815481529060010190602001808311610ba357829003601f168201915b505050505091505090565b335f81815260126020526040812054909190421015610bfd5760405163de1af48d60e01b815260040160405180910390fd5b610c078484612300565b91505b5092915050565b604080518082019091525f80825260208201526060610c4160405180604001604052805f81526020015f81525090565b6040805180820182525f8082526001600160401b03602080840182905284518381529081019094529195509182610c9a565b604080518082019091525f815260606020820152815260200190600190039081610c735790505b5093505f80610cbe604089013560608a0135610cb960208c018c6139d8565b612317565b60408051808201909152918252602082015296989597505050505050565b5f807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610d60576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610d7a90610d75908a6139d8565b61235a565b14610db857610d8c60208801886139d8565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610d57565b610dc7878787878787876123aa565b50505050505050565b6001600160a01b0383165f908152601260205260408120548490421015610e0a5760405163de1af48d60e01b815260040160405180910390fd5b610e15858585612508565b95945050505050565b60025f5403610e40576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff1615610e68576040516308db0db560e11b815260040160405180910390fd5b610e7061252b565b6004805460ff191660011790555f5b83811015610ee257600160105f878785818110610e9e57610e9e613bdc565b9050602002016020810190610eb39190613306565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055600101610e7f565b505f5b81811015610f4857600160115f858585818110610f0457610f04613bdc565b9050602002016020810190610f199190613306565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055600101610ee5565b505060015f55505050565b6004545f90600161010090910460ff1610610f775750600454610100900460ff1690565b50601290565b610f8561252b565b63ffffffff82165f8181525f805160206144bc833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b604080518082019091525f80825260208201525f61101660408501356060860135610cb960208801886139d8565b9150505f80611025868461255d565b909250905061104261103a60208801886139d8565b83838861269d565b93505050505b92915050565b60025f5403611070576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166110975760405163d311bc3960e01b815260040160405180910390fd5b335f9081526010602052604090205460ff166110c65760405163955c501b60e01b815260040160405180910390fd5b6110d08282612772565b505060015f55565b5f6110e16127aa565b805490915060ff600160401b82041615906001600160401b03165f811580156111075750825b90505f826001600160401b031660011480156111225750303b155b905081158015611130575080155b1561114e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561117857845460ff60401b1916600160401b1785555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111bf57604051632d6ce9fd60e11b815260040160405180910390fd5b60016111cb8782613c34565b506040805180820190915260018152603160f81b60208201526002906111f19082613c34565b507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60016040516112229190613cee565b604051809103902060026040516112399190613cee565b60408051918290038220602083019490945281019190915260608101919091524660808201523060a082015260c00160408051808303601f1901815291905280516020909101206003556004805461ff00191661010060ff8b16021790556112a0896127d2565b6112ab86888b6127f0565b83156112f157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b63ffffffff82165f9081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061134f90613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461137b90613baa565b80156113c65780601f1061139d576101008083540402835291602001916113c6565b820191905f5260205f20905b8154815290600101906020018083116113a957829003601f168201915b505050505091505092915050565b6113dc61252b565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a15050565b61145861252b565b6114615f6127d2565b565b60025f5403611485576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166114ac5760405163d311bc3960e01b815260040160405180910390fd5b6004546201000090046001600160a01b031633146114dc576040516282b42960e81b815260040160405180910390fd5b6114e5336127d2565b60015f55565b6001600160a01b03811630145b949350505050565b5f6060805f805f60605f801b6003540361152d57604051633dca919960e11b815260040160405180910390fd5b604080515f8082526020820190925260018054600f60f81b9391926002924692309290869061155b90613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461158790613baa565b80156115d25780601f106115a9576101008083540402835291602001916115d2565b820191905f5260205f20905b8154815290600101906020018083116115b557829003601f168201915b505050505095508480546115e590613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461161190613baa565b801561165c5780601f106116335761010080835404028352916020019161165c565b820191905f5260205f20905b81548152906001019060200180831161163f57829003601f168201915b50505050509450965096509650965096509650965090919293949596565b5f807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610d00565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f8051602061449c83398151915291610b4990613baa565b60025f5403611702576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166117295760405163d311bc3960e01b815260040160405180910390fd5b335f9081526011602052604090205460ff166117585760405163a9c455db60e01b815260040160405180910390fd5b6110d08282612810565b335f818152601260205260408120549091904210156117945760405163de1af48d60e01b815260040160405180910390fd5b610c078484612844565b60025f54036117c0576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166117e75760405163d311bc3960e01b815260040160405180910390fd5b6117ef61252b565b6117fb81610384613d73565b6001600160a01b0383165f818152601260209081526040918290209390935580519182529181018390527f65160825020ceacdd81c96ed4447b05dd1ac1ed7f2c67a876ffcfa4b55e85297910160405180910390a1505060015f55565b5f807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610d00565b61188861252b565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00005f5b828110156119ca576118ed8484838181106118c8576118c8613bdc565b90506020028101906118da9190613d86565b6118e8906040810190613da4565b612851565b8383828181106118ff576118ff613bdc565b90506020028101906119119190613d86565b61191f906040810190613da4565b835f87878681811061193357611933613bdc565b90506020028101906119459190613d86565b6119539060208101906139d8565b63ffffffff1663ffffffff1681526020019081526020015f205f87878681811061197f5761197f613bdc565b90506020028101906119919190613d86565b6119a2906040810190602001613de6565b61ffff16815260208101919091526040015f20916119c1919083613dff565b506001016118ab565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6748383604051610fdb929190613ee0565b63ffffffff84165f9081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611a4e90613baa565b80601f0160208091040260200160405190810160405280929190818152602001828054611a7a90613baa565b8015611ac55780601f10611a9c57610100808354040283529160200191611ac5565b820191905f5260205f20905b815481529060010190602001808311611aa857829003601f168201915b5050505050905080515f03611b145784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509295506114f8945050505050565b5f849003611b255791506114f89050565b60028410611b6f57611b378585612851565b80611b458560028189613fc5565b604051602001611b5793929190614003565b604051602081830303815290604052925050506114f8565b8484604051639a6d49cd60e01b8152600401610d57929190614021565b5f5b81811015611c9b5736838383818110611ba957611ba9613bdc565b9050602002810190611bbb9190614034565b9050611bf9611bcd60208301836139d8565b602083013563ffffffff919091165f9081525f805160206144bc83398151915260205260409020541490565b611c035750611c93565b3063d045a0dc60c08301358360a0810135611c22610100830183613da4565b611c33610100890160e08a01613306565b611c416101208a018a613da4565b6040518963ffffffff1660e01b8152600401611c63979695949392919061405d565b5f604051808303818588803b158015611c7a575f80fd5b505af1158015611c8c573d5f803e3d5ffd5b5050505050505b600101611b8e565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b81526004015f60405180830381865afa158015611cd7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cfe91908101906140e2565b604051638351eea760e01b8152600401610d57919061334f565b611d206132af565b604080518082019091525f80825260208201525f80611d5533604089013560608a0135611d5060208c018c6139d8565b612892565b915091505f80611d65898461255d565b9092509050611d91611d7a60208b018b6139d8565b8383611d8b368d90038d018d614156565b8b6128b7565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611ddf908d018d6139d8565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611e1861252b565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e1906024015f604051808303815f87803b158015611e78575f80fd5b505af1158015611e8a573d5f803e3d5ffd5b5050505050565b60025f5403611eb3576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff16611eda5760405163d311bc3960e01b815260040160405180910390fd5b611ee261252b565b6001600160a01b0381165f9081526012602052604090205460011115611f1b5760405163d5b25b6360e01b815260040160405180910390fd5b6001600160a01b0381165f90815260126020526040902054421015611f535760405163de1af48d60e01b815260040160405180910390fd5b6001600160a01b0381165f8181526012602090815260408083209290925590519182527f3df361550ba0c4d62241737fbf0cb45fa2eb1cc0844344b79d3be34dbfb21e5b910160405180910390a15060015f55565b333014611fc85760405163029a949d60e31b815260040160405180910390fd5b610dc787878787878787610db8565b611fdf61252b565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001611444565b60025f540361206d576040516306fda65d60e31b815260040160405180910390fd5b60025f55428410156120925760405163f87d927160e01b815260040160405180910390fd5b6003546001600160a01b038881165f8181526005602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e0840194859052805191012061190160f01b845260e2830194909452610102909101929092526042902090612140828686866129bd565b9050886001600160a01b0316816001600160a01b03161461217457604051632057875960e21b815260040160405180910390fd5b6001600160a01b0389165f90815260056020526040812080549161219783614187565b91905055506121a7898989612a84565b505060015f5550505050505050565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60025f5403612221576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166122485760405163d311bc3960e01b815260040160405180910390fd5b61225061252b565b6001600160a01b0381166122775760405163d92e233d60e01b815260040160405180910390fd5b6004805462010000600160b01b031916620100006001600160a01b038416908102919091179091556122a761167a565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35060015f55565b5f602082018035906122f99061095890856139d8565b1492915050565b5f3361230d818585612a84565b5060019392505050565b5f8061232285612a91565b915081905083811015612352576040516371c4efed60e01b81526004810182905260248101859052604401610d57565b935093915050565b63ffffffff81165f9081525f805160206144bc83398151915260208190526040822054806123a35760405163f6ff4fb760e01b815263ffffffff85166004820152602401610d57565b9392505050565b5f6123bb6123b88787612ac7565b90565b90505f6123e6826123d46123cf8a8a612ade565b612b00565b6123e160208d018d6139d8565b612b34565b905060288611156124a6575f61242261240560608c0160408d0161419f565b61241260208d018d6139d8565b8461241d8c8c612b5b565b612ba5565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906124779086908d905f9087906004016141ba565b5f604051808303815f87803b15801561248e575f80fd5b505af11580156124a0573d5f803e3d5ffd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6124df60208d018d6139d8565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b5f33612515858285612bd7565b612520858585612c3b565b506001949350505050565b3361253461167a565b6001600160a01b0316146114615760405163118cdaa760e01b8152336004820152602401610d57565b6060805f6125b8856020013561257286612c98565b61257f60a0890189613da4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612cc392505050565b90935090505f816125ca5760016125cd565b60025b90506125ed6125df60208801886139d8565b8261099560808a018a613da4565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156126925760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061265190899089906004016141f4565b602060405180830381865afa15801561266c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126909190614218565b505b505050509250929050565b604080518082019091525f80825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff1681526020016126ff8961235a565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612734929190614233565b6040805180830381865afa15801561274e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1591906142da565b6001600160a01b03821661279b5760405163ec442f0560e01b81525f6004820152602401610d57565b6127a65f8383612d3d565b5050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00611048565b6004805462010000600160b01b03191690556127ed81612e76565b50565b6127f8612ee6565b6128028383612f0b565b61280b81612f1d565b505050565b6001600160a01b03821661283957604051634b637e8f60e11b81525f6004820152602401610d57565b6127a6825f83612d3d565b5f3361230d818585612c3b565b5f61285f6002828486613fc5565b612868916142f4565b60f01c90506003811461280b578282604051639a6d49cd60e01b8152600401610d57929190614021565b5f8061289f858585612317565b90925090506128ae8683612810565b94509492505050565b6128bf6132af565b5f6128cc845f0151612f3e565b6020850151909150156128e6576128e68460200151612f65565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016129368c61235a565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401612971929190614233565b60806040518083038185885af115801561298d573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906129b2919061432a565b979650505050505050565b5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156129ff57604051637a02652b60e11b815260040160405180910390fd5b604080515f8082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612a50573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610e1557604051638baa579f60e01b815260040160405180910390fd5b61280b8383836001613044565b5f7f0000000000000000000000000000000000000000000000000000000000000000612abd8184614391565b61104891906143b0565b5f612ad56020828486613fc5565b6123a3916143c7565b5f612aed602860208486613fc5565b612af6916143e4565b60c01c9392505050565b5f6110487f00000000000000000000000000000000000000000000000000000000000000006001600160401b0384166143b0565b5f6001600160a01b038416612b495761dead93505b612b538484612772565b509092915050565b6060612b6a8260288186613fc5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929695505050505050565b606084848484604051602001612bbe949392919061441a565b6040516020818303038152906040529050949350505050565b5f612be284846121b6565b90505f19811015612c355781811015612c2757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610d57565b612c3584848484035f613044565b50505050565b6001600160a01b038316612c6457604051634b637e8f60e11b81525f6004820152602401610d57565b6001600160a01b038216612c8d5760405163ec442f0560e01b81525f6004820152602401610d57565b61280b838383612d3d565b5f6110487f000000000000000000000000000000000000000000000000000000000000000083614391565b8051606090151580612d0c578484604051602001612cf892919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052612d33565b84843385604051602001612d239493929190614454565b6040516020818303038152906040525b9150935093915050565b5f8051602061449c8339815191526001600160a01b038416612d775781816002015f828254612d6c9190613d73565b90915550612de79050565b6001600160a01b0384165f9081526020829052604090205482811015612dc95760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610d57565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b038316612e05576002810180548390039055612e23565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e6891815260200190565b60405180910390a350505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b612eee613127565b61146157604051631afcd79f60e31b815260040160405180910390fd5b612f13612ee6565b6127a68282613140565b612f25612ee6565b612f2e81613190565b612f366131a1565b6127ed6131a1565b5f813414612f61576040516304fb820960e51b8152346004820152602401610d57565b5090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fe69190614480565b90506001600160a01b03811661300f576040516329b99a9560e11b815260040160405180910390fd5b6127a66001600160a01b038216337f0000000000000000000000000000000000000000000000000000000000000000856131a9565b5f8051602061449c8339815191526001600160a01b03851661307b5760405163e602df0560e01b81525f6004820152602401610d57565b6001600160a01b0384166130a457604051634a1406b160e11b81525f6004820152602401610d57565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115611e8a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161311891815260200190565b60405180910390a35050505050565b5f6131306127aa565b54600160401b900460ff16919050565b613148612ee6565b5f8051602061449c8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036131818482613c34565b5060048101612c358382613c34565b613198612ee6565b612f2e81613203565b611461612ee6565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612c35908590613214565b61320b612ee6565b6127ed81613280565b5f8060205f8451602086015f885af180613233576040513d5f823e3d81fd5b50505f513d9150811561324a578060011415613257565b6001600160a01b0384163b155b15612c3557604051635274afe760e01b81526001600160a01b0385166004820152602401610d57565b613288612ee6565b6001600160a01b038116611e1857604051632d618d8160e21b815260040160405180910390fd5b60405180606001604052805f80191681526020015f6001600160401b031681526020016132ed60405180604001604052805f81526020015f81525090565b905290565b6001600160a01b03811681146127ed575f80fd5b5f60208284031215613316575f80fd5b81356123a3816132f2565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6123a36020830184613321565b5f8060408385031215613372575f80fd5b823561337d816132f2565b946020939093013593505050565b5f60e0828403121561339b575f80fd5b50919050565b5f602082840312156133b1575f80fd5b81356001600160401b038111156133c6575f80fd5b610c078482850161338b565b83518152602080850151908201525f60a0820160a0604084015280855180835260c08501915060c08160051b8601019250602087015f5b828110156134515760bf19878603018452815180518652602081015190506040602087015261343b6040870182613321565b9550506020938401939190910190600101613409565b50508551606086015250506020840151608084015290506114f8565b5f6060828403121561339b575f80fd5b5f8083601f84011261348d575f80fd5b5081356001600160401b038111156134a3575f80fd5b6020830191508360208285010111156134ba575f80fd5b9250929050565b5f805f805f805f60e0888a0312156134d7575f80fd5b6134e1898961346d565b96506060880135955060808801356001600160401b03811115613502575f80fd5b61350e8a828b0161347d565b90965094505060a0880135613522816132f2565b925060c08801356001600160401b0381111561353c575f80fd5b6135488a828b0161347d565b989b979a50959850939692959293505050565b5f805f6060848603121561356d575f80fd5b8335613578816132f2565b92506020840135613588816132f2565b929592945050506040919091013590565b5f8083601f8401126135a9575f80fd5b5081356001600160401b038111156135bf575f80fd5b6020830191508360208260051b85010111156134ba575f80fd5b5f805f80604085870312156135ec575f80fd5b84356001600160401b03811115613601575f80fd5b61360d87828801613599565b90955093505060208501356001600160401b0381111561362b575f80fd5b61363787828801613599565b95989497509550505050565b803563ffffffff81168114613656575f80fd5b919050565b5f806040838503121561366c575f80fd5b61337d83613643565b80151581146127ed575f80fd5b5f8060408385031215613693575f80fd5b82356001600160401b038111156136a8575f80fd5b6136b48582860161338b565b92505060208301356136c581613675565b809150509250929050565b815181526020808301519082015260408101611048565b803560ff81168114613656575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b038111828210171561372d5761372d6136f7565b60405290565b604051601f8201601f191681016001600160401b038111828210171561375b5761375b6136f7565b604052919050565b5f6001600160401b0382111561377b5761377b6136f7565b50601f01601f191660200190565b5f82601f830112613798575f80fd5b81356137ab6137a682613763565b613733565b8181528460208386010111156137bf575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f80608085870312156137ee575f80fd5b84356137f9816132f2565b9350613807602086016136e7565b925060408501356001600160401b03811115613821575f80fd5b61382d87828801613789565b92505060608501356001600160401b03811115613848575f80fd5b61385487828801613789565b91505092959194509250565b803561ffff81168114613656575f80fd5b5f8060408385031215613882575f80fd5b61388b83613643565b915061389960208401613860565b90509250929050565b5f805f8060a085870312156138b5575f80fd5b6138bf868661346d565b935060608501356001600160401b038111156138d9575f80fd5b6138e58782880161347d565b90945092505060808501356138f9816132f2565b939692955090935050565b60ff60f81b8816815260e060208201525f61392260e0830189613321565b82810360408401526139348189613321565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561398957835183526020938401939092019160010161396b565b50909b9a5050505050505050505050565b5f80602083850312156139ab575f80fd5b82356001600160401b038111156139c0575f80fd5b6139cc85828601613599565b90969095509350505050565b5f602082840312156139e8575f80fd5b6123a382613643565b5f805f8060608587031215613a04575f80fd5b613a0d85613643565b9350613a1b60208601613860565b925060408501356001600160401b03811115613a35575f80fd5b6136378782880161347d565b5f805f8385036080811215613a54575f80fd5b84356001600160401b03811115613a69575f80fd5b613a758782880161338b565b9450506040601f1982011215613a89575f80fd5b506020840191506060840135613a9e816132f2565b809150509250925092565b5f60c082019050835182526001600160401b0360208501511660208301526040840151613ae3604084018280518252602090810151910152565b5082516080830152602083015160a08301526123a3565b5f805f805f805f60e0888a031215613b10575f80fd5b8735613b1b816132f2565b96506020880135613b2b816132f2565b95506040880135945060608801359350613b47608089016136e7565b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215613b75575f80fd5b8235613b80816132f2565b915060208301356136c5816132f2565b5f60608284031215613ba0575f80fd5b6123a3838361346d565b600181811c90821680613bbe57607f821691505b60208210810361339b57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b601f82111561280b57805f5260205f20601f840160051c81016020851015613c155750805b601f840160051c820191505b81811015611e8a575f8155600101613c21565b81516001600160401b03811115613c4d57613c4d6136f7565b613c6181613c5b8454613baa565b84613bf0565b6020601f821160018114613c93575f8315613c7c5750848201515b5f19600385901b1c1916600184901b178455611e8a565b5f84815260208120601f198516915b82811015613cc25787850151825560209485019460019092019101613ca2565b5084821015613cdf57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f808354613cfb81613baa565b600182168015613d125760018114613d2757613d54565b60ff1983168652811515820286019350613d54565b865f5260205f205f5b83811015613d4c57815488820152600190910190602001613d30565b505081860193505b509195945050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561104857611048613d5f565b5f8235605e19833603018112613d9a575f80fd5b9190910192915050565b5f808335601e19843603018112613db9575f80fd5b8301803591506001600160401b03821115613dd2575f80fd5b6020019150368190038213156134ba575f80fd5b5f60208284031215613df6575f80fd5b6123a382613860565b6001600160401b03831115613e1657613e166136f7565b613e2a83613e248354613baa565b83613bf0565b5f601f841160018114613e5b575f8515613e445750838201355b5f19600387901b1c1916600186901b178355611e8a565b5f83815260208120601f198716915b82811015613e8a5786850135825560209485019460019092019101613e6a565b5086821015613ea6575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602080825281018290525f6040600584901b830181019083018583605e1936839003015b87821015613fb857868503603f190184528235818112613f22575f80fd5b890163ffffffff613f3282613643565b16865261ffff613f4460208301613860565b1660208701526040810135601e19823603018112613f60575f80fd5b016020810190356001600160401b03811115613f7a575f80fd5b803603821315613f88575f80fd5b60606040880152613f9d606088018284613eb8565b96505050602083019250602084019350600182019150613f04565b5092979650505050505050565b5f8085851115613fd3575f80fd5b83861115613fdf575f80fd5b5050820193919092039150565b5f81518060208401855e5f93019283525090919050565b5f61400e8286613fec565b838582375f930192835250909392505050565b602081525f6114f8602083018486613eb8565b5f823561013e19833603018112613d9a575f80fd5b6001600160401b03811681146127ed575f80fd5b63ffffffff61406b89613643565b168152602088810135908201525f604089013561408781614049565b6001600160401b03811660408401525087606083015260e060808301526140b260e083018789613eb8565b6001600160a01b03861660a084015282810360c08401526140d4818587613eb8565b9a9950505050505050505050565b5f602082840312156140f2575f80fd5b81516001600160401b03811115614107575f80fd5b8201601f81018413614117575f80fd5b80516141256137a682613763565b818152856020838501011115614139575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b5f6040828403128015614167575f80fd5b5061417061370b565b823581526020928301359281019290925250919050565b5f6001820161419857614198613d5f565b5060010190565b5f602082840312156141af575f80fd5b81356123a381614049565b60018060a01b038516815283602082015261ffff83166040820152608060608201525f6141ea6080830184613321565b9695505050505050565b604081525f6142066040830185613321565b8281036020840152610e158185613321565b5f60208284031215614228575f80fd5b81516123a381613675565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a0608084015261426860e0840182613321565b90506060850151603f198483030160a08501526142858282613321565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f604082840312156142bb575f80fd5b6142c361370b565b825181526020928301519281019290925250919050565b5f604082840312156142ea575f80fd5b6123a383836142ab565b80356001600160f01b03198116906002841015610c0a576001600160f01b031960029490940360031b84901b1690921692915050565b5f608082840312801561433b575f80fd5b50604051606081016001600160401b038111828210171561435e5761435e6136f7565b60405282518152602083015161437381614049565b602082015261438584604085016142ab565b60408201529392505050565b5f826143ab57634e487b7160e01b5f52601260045260245ffd5b500490565b808202811582820484141761104857611048613d5f565b80356020831015611048575f19602084900360031b1b1692915050565b80356001600160c01b03198116906008841015610c0a576001600160c01b031960089490940360031b84901b1690921692915050565b60c085901b6001600160c01b031916815260e084901b6001600160e01b0319166008820152600c81018390525f6141ea602c830184613fec565b8481526001600160401b0360c01b8460c01b1660208201528260288201525f6141ea6048830184613fec565b5f60208284031215614490575f80fd5b81516123a3816132f256fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220b28d93f9c39f9e9b08eb020938d3ac2d50af7b10d52d8d6f49e5928cf6700b5864736f6c634300081a00330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode
0x608060405260043610610366575f3560e01c80637d25a05e116101c8578063bb0b6a53116100fd578063d42438851161009d578063f2fde38b1161006d578063f2fde38b14610a9f578063f46eccc414610abe578063fc0c546a1461064f578063ff7bd03d14610aec575f80fd5b8063d424388514610a1f578063d505accf14610a3e578063dd62ed3e14610a5d578063e30c397814610a7c575f80fd5b8063c7c7f5b3116100d8578063c7c7f5b3146109ad578063ca5eb5e1146109ce578063cb67f948146109ed578063d045a0dc14610a0c575f80fd5b8063bb0b6a531461093e578063bc70b3541461097b578063bd815db01461099a575f80fd5b8063963efcaa11610168578063a9059cbb11610143578063a9059cbb146108cd578063b1c25586146108ec578063b731ea0a1461090b578063b98bd0701461091f575f80fd5b8063963efcaa146108695780639dc29fac1461089c5780639f68b964146108bb575f80fd5b806384b0196e116101a357806384b0196e14610807578063857749b01461082e5780638da5cb5b1461084157806395d89b4114610855575f80fd5b80637d25a05e1461077b5780637ecebe00146107b457806382413eac146107e8575f80fd5b8063313ce5671161029e5780635535d4611161023e5780636fc1b31e116102195780636fc1b31e146106f457806370a0823114610713578063715018a61461075357806379ba509714610767575f80fd5b80635535d461146106615780635a0dfe4d146106805780635e280f11146106c1575f80fd5b80633b6f743b116102795780633b6f743b146105e557806340c10f191461061157806342fe09801461063057806352ae28791461064f575f80fd5b8063313ce5671461058c5780633400288b146105b25780633644e515146105d1575f80fd5b8063156a0d0f116103095780631f5e1334116102e45780631f5e13341461050757806323b872dd1461051b57806323ff63a61461053a57806330adf81f14610559575f80fd5b8063156a0d0f1461048357806317442b70146104a957806318160ddd146104ca575f80fd5b80630d35b415116103445780630d35b415146103ed578063111ecdad1461041b57806313137d6514610447578063134d4f251461045c575f80fd5b806303d41e0e1461036a57806306fdde03146103ad578063095ea7b3146103ce575b5f80fd5b348015610375575f80fd5b50610398610384366004613306565b60116020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103b8575f80fd5b506103c1610b0b565b6040516103a4919061334f565b3480156103d9575f80fd5b506103986103e8366004613361565b610bcb565b3480156103f8575f80fd5b5061040c6104073660046133a1565b610c11565b6040516103a4939291906133d2565b348015610426575f80fd5b5061042f610cdc565b6040516001600160a01b0390911681526020016103a4565b61045a6104553660046134c1565b610d10565b005b348015610467575f80fd5b50610470600281565b60405161ffff90911681526020016103a4565b34801561048e575f80fd5b506040805162b9270b60e21b815260016020820152016103a4565b3480156104b4575f80fd5b50604080516001815260026020820152016103a4565b3480156104d5575f80fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016103a4565b348015610512575f80fd5b50610470600181565b348015610526575f80fd5b5061039861053536600461355b565b610dd0565b348015610545575f80fd5b5061045a6105543660046135d9565b610e1e565b348015610564575f80fd5b506104f97f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b348015610597575f80fd5b506105a0610f53565b60405160ff90911681526020016103a4565b3480156105bd575f80fd5b5061045a6105cc36600461365b565b610f7d565b3480156105dc575f80fd5b506003546104f9565b3480156105f0575f80fd5b506106046105ff366004613682565b610fe8565b6040516103a491906136d0565b34801561061c575f80fd5b5061045a61062b366004613361565b61104e565b34801561063b575f80fd5b5061045a61064a3660046137db565b6110d8565b34801561065a575f80fd5b503061042f565b34801561066c575f80fd5b506103c161067b366004613871565b6112fc565b34801561068b575f80fd5b5061039861069a36600461365b565b63ffffffff919091165f9081525f805160206144bc83398151915260205260409020541490565b3480156106cc575f80fd5b5061042f7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b3480156106ff575f80fd5b5061045a61070e366004613306565b6113d4565b34801561071e575f80fd5b506104f961072d366004613306565b6001600160a01b03165f9081525f8051602061449c833981519152602052604090205490565b34801561075e575f80fd5b5061045a611450565b348015610772575f80fd5b5061045a611463565b348015610786575f80fd5b5061079c61079536600461365b565b5f92915050565b6040516001600160401b0390911681526020016103a4565b3480156107bf575f80fd5b506104f96107ce366004613306565b6001600160a01b03165f9081526005602052604090205490565b3480156107f3575f80fd5b506103986108023660046138a2565b6114eb565b348015610812575f80fd5b5061081b611500565b6040516103a49796959493929190613904565b348015610839575f80fd5b5060066105a0565b34801561084c575f80fd5b5061042f61167a565b348015610860575f80fd5b506103c16116a2565b348015610874575f80fd5b506104f97f000000000000000000000000000000000000000000000000000000e8d4a5100081565b3480156108a7575f80fd5b5061045a6108b6366004613361565b6116e0565b3480156108c6575f80fd5b505f610398565b3480156108d8575f80fd5b506103986108e7366004613361565b611762565b3480156108f7575f80fd5b5061045a610906366004613361565b61179e565b348015610916575f80fd5b5061042f611858565b34801561092a575f80fd5b5061045a61093936600461399a565b611880565b348015610949575f80fd5b506104f96109583660046139d8565b63ffffffff165f9081525f805160206144bc833981519152602052604090205490565b348015610986575f80fd5b506103c16109953660046139f1565b6119fc565b61045a6109a836600461399a565b611b8c565b6109c06109bb366004613a41565b611d18565b6040516103a4929190613aa9565b3480156109d9575f80fd5b5061045a6109e8366004613306565b611e10565b3480156109f8575f80fd5b5061045a610a07366004613306565b611e91565b61045a610a1a3660046134c1565b611fa8565b348015610a2a575f80fd5b5061045a610a39366004613306565b611fd7565b348015610a49575f80fd5b5061045a610a58366004613afa565b61204b565b348015610a68575f80fd5b506104f9610a77366004613b64565b6121b6565b348015610a87575f80fd5b506004546201000090046001600160a01b031661042f565b348015610aaa575f80fd5b5061045a610ab9366004613306565b6121ff565b348015610ac9575f80fd5b50610398610ad8366004613306565b60106020525f908152604090205460ff1681565b348015610af7575f80fd5b50610398610b06366004613b90565b6122e3565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060915f8051602061449c83398151915291610b4990613baa565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7590613baa565b8015610bc05780601f10610b9757610100808354040283529160200191610bc0565b820191905f5260205f20905b815481529060010190602001808311610ba357829003601f168201915b505050505091505090565b335f81815260126020526040812054909190421015610bfd5760405163de1af48d60e01b815260040160405180910390fd5b610c078484612300565b91505b5092915050565b604080518082019091525f80825260208201526060610c4160405180604001604052805f81526020015f81525090565b6040805180820182525f8082526001600160401b03602080840182905284518381529081019094529195509182610c9a565b604080518082019091525f815260606020820152815260200190600190039081610c735790505b5093505f80610cbe604089013560608a0135610cb960208c018c6139d8565b612317565b60408051808201909152918252602082015296989597505050505050565b5f807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610d60576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610d7a90610d75908a6139d8565b61235a565b14610db857610d8c60208801886139d8565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610d57565b610dc7878787878787876123aa565b50505050505050565b6001600160a01b0383165f908152601260205260408120548490421015610e0a5760405163de1af48d60e01b815260040160405180910390fd5b610e15858585612508565b95945050505050565b60025f5403610e40576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff1615610e68576040516308db0db560e11b815260040160405180910390fd5b610e7061252b565b6004805460ff191660011790555f5b83811015610ee257600160105f878785818110610e9e57610e9e613bdc565b9050602002016020810190610eb39190613306565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055600101610e7f565b505f5b81811015610f4857600160115f858585818110610f0457610f04613bdc565b9050602002016020810190610f199190613306565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055600101610ee5565b505060015f55505050565b6004545f90600161010090910460ff1610610f775750600454610100900460ff1690565b50601290565b610f8561252b565b63ffffffff82165f8181525f805160206144bc833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b604080518082019091525f80825260208201525f61101660408501356060860135610cb960208801886139d8565b9150505f80611025868461255d565b909250905061104261103a60208801886139d8565b83838861269d565b93505050505b92915050565b60025f5403611070576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166110975760405163d311bc3960e01b815260040160405180910390fd5b335f9081526010602052604090205460ff166110c65760405163955c501b60e01b815260040160405180910390fd5b6110d08282612772565b505060015f55565b5f6110e16127aa565b805490915060ff600160401b82041615906001600160401b03165f811580156111075750825b90505f826001600160401b031660011480156111225750303b155b905081158015611130575080155b1561114e5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561117857845460ff60401b1916600160401b1785555b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03166111bf57604051632d6ce9fd60e11b815260040160405180910390fd5b60016111cb8782613c34565b506040805180820190915260018152603160f81b60208201526002906111f19082613c34565b507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60016040516112229190613cee565b604051809103902060026040516112399190613cee565b60408051918290038220602083019490945281019190915260608101919091524660808201523060a082015260c00160408051808303601f1901815291905280516020909101206003556004805461ff00191661010060ff8b16021790556112a0896127d2565b6112ab86888b6127f0565b83156112f157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b63ffffffff82165f9081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061134f90613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461137b90613baa565b80156113c65780601f1061139d576101008083540402835291602001916113c6565b820191905f5260205f20905b8154815290600101906020018083116113a957829003601f168201915b505050505091505092915050565b6113dc61252b565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a15050565b61145861252b565b6114615f6127d2565b565b60025f5403611485576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166114ac5760405163d311bc3960e01b815260040160405180910390fd5b6004546201000090046001600160a01b031633146114dc576040516282b42960e81b815260040160405180910390fd5b6114e5336127d2565b60015f55565b6001600160a01b03811630145b949350505050565b5f6060805f805f60605f801b6003540361152d57604051633dca919960e11b815260040160405180910390fd5b604080515f8082526020820190925260018054600f60f81b9391926002924692309290869061155b90613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461158790613baa565b80156115d25780601f106115a9576101008083540402835291602001916115d2565b820191905f5260205f20905b8154815290600101906020018083116115b557829003601f168201915b505050505095508480546115e590613baa565b80601f016020809104026020016040519081016040528092919081815260200182805461161190613baa565b801561165c5780601f106116335761010080835404028352916020019161165c565b820191905f5260205f20905b81548152906001019060200180831161163f57829003601f168201915b50505050509450965096509650965096509650965090919293949596565b5f807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610d00565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f8051602061449c83398151915291610b4990613baa565b60025f5403611702576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166117295760405163d311bc3960e01b815260040160405180910390fd5b335f9081526011602052604090205460ff166117585760405163a9c455db60e01b815260040160405180910390fd5b6110d08282612810565b335f818152601260205260408120549091904210156117945760405163de1af48d60e01b815260040160405180910390fd5b610c078484612844565b60025f54036117c0576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166117e75760405163d311bc3960e01b815260040160405180910390fd5b6117ef61252b565b6117fb81610384613d73565b6001600160a01b0383165f818152601260209081526040918290209390935580519182529181018390527f65160825020ceacdd81c96ed4447b05dd1ac1ed7f2c67a876ffcfa4b55e85297910160405180910390a1505060015f55565b5f807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610d00565b61188861252b565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00005f5b828110156119ca576118ed8484838181106118c8576118c8613bdc565b90506020028101906118da9190613d86565b6118e8906040810190613da4565b612851565b8383828181106118ff576118ff613bdc565b90506020028101906119119190613d86565b61191f906040810190613da4565b835f87878681811061193357611933613bdc565b90506020028101906119459190613d86565b6119539060208101906139d8565b63ffffffff1663ffffffff1681526020019081526020015f205f87878681811061197f5761197f613bdc565b90506020028101906119919190613d86565b6119a2906040810190602001613de6565b61ffff16815260208101919091526040015f20916119c1919083613dff565b506001016118ab565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6748383604051610fdb929190613ee0565b63ffffffff84165f9081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611a4e90613baa565b80601f0160208091040260200160405190810160405280929190818152602001828054611a7a90613baa565b8015611ac55780601f10611a9c57610100808354040283529160200191611ac5565b820191905f5260205f20905b815481529060010190602001808311611aa857829003601f168201915b5050505050905080515f03611b145784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509295506114f8945050505050565b5f849003611b255791506114f89050565b60028410611b6f57611b378585612851565b80611b458560028189613fc5565b604051602001611b5793929190614003565b604051602081830303815290604052925050506114f8565b8484604051639a6d49cd60e01b8152600401610d57929190614021565b5f5b81811015611c9b5736838383818110611ba957611ba9613bdc565b9050602002810190611bbb9190614034565b9050611bf9611bcd60208301836139d8565b602083013563ffffffff919091165f9081525f805160206144bc83398151915260205260409020541490565b611c035750611c93565b3063d045a0dc60c08301358360a0810135611c22610100830183613da4565b611c33610100890160e08a01613306565b611c416101208a018a613da4565b6040518963ffffffff1660e01b8152600401611c63979695949392919061405d565b5f604051808303818588803b158015611c7a575f80fd5b505af1158015611c8c573d5f803e3d5ffd5b5050505050505b600101611b8e565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b81526004015f60405180830381865afa158015611cd7573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cfe91908101906140e2565b604051638351eea760e01b8152600401610d57919061334f565b611d206132af565b604080518082019091525f80825260208201525f80611d5533604089013560608a0135611d5060208c018c6139d8565b612892565b915091505f80611d65898461255d565b9092509050611d91611d7a60208b018b6139d8565b8383611d8b368d90038d018d614156565b8b6128b7565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611ddf908d018d6139d8565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b611e1861252b565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e1906024015f604051808303815f87803b158015611e78575f80fd5b505af1158015611e8a573d5f803e3d5ffd5b5050505050565b60025f5403611eb3576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff16611eda5760405163d311bc3960e01b815260040160405180910390fd5b611ee261252b565b6001600160a01b0381165f9081526012602052604090205460011115611f1b5760405163d5b25b6360e01b815260040160405180910390fd5b6001600160a01b0381165f90815260126020526040902054421015611f535760405163de1af48d60e01b815260040160405180910390fd5b6001600160a01b0381165f8181526012602090815260408083209290925590519182527f3df361550ba0c4d62241737fbf0cb45fa2eb1cc0844344b79d3be34dbfb21e5b910160405180910390a15060015f55565b333014611fc85760405163029a949d60e31b815260040160405180910390fd5b610dc787878787878787610db8565b611fdf61252b565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001611444565b60025f540361206d576040516306fda65d60e31b815260040160405180910390fd5b60025f55428410156120925760405163f87d927160e01b815260040160405180910390fd5b6003546001600160a01b038881165f8181526005602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98185015280830195909552948c166060850152608084018b905260a084019490945260c08084018a90528451808503909101815260e0840194859052805191012061190160f01b845260e2830194909452610102909101929092526042902090612140828686866129bd565b9050886001600160a01b0316816001600160a01b03161461217457604051632057875960e21b815260040160405180910390fd5b6001600160a01b0389165f90815260056020526040812080549161219783614187565b91905055506121a7898989612a84565b505060015f5550505050505050565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60025f5403612221576040516306fda65d60e31b815260040160405180910390fd5b60025f5560045460ff166122485760405163d311bc3960e01b815260040160405180910390fd5b61225061252b565b6001600160a01b0381166122775760405163d92e233d60e01b815260040160405180910390fd5b6004805462010000600160b01b031916620100006001600160a01b038416908102919091179091556122a761167a565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35060015f55565b5f602082018035906122f99061095890856139d8565b1492915050565b5f3361230d818585612a84565b5060019392505050565b5f8061232285612a91565b915081905083811015612352576040516371c4efed60e01b81526004810182905260248101859052604401610d57565b935093915050565b63ffffffff81165f9081525f805160206144bc83398151915260208190526040822054806123a35760405163f6ff4fb760e01b815263ffffffff85166004820152602401610d57565b9392505050565b5f6123bb6123b88787612ac7565b90565b90505f6123e6826123d46123cf8a8a612ade565b612b00565b6123e160208d018d6139d8565b612b34565b905060288611156124a6575f61242261240560608c0160408d0161419f565b61241260208d018d6139d8565b8461241d8c8c612b5b565b612ba5565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb59012906124779086908d905f9087906004016141ba565b5f604051808303815f87803b15801561248e575f80fd5b505af11580156124a0573d5f803e3d5ffd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6124df60208d018d6139d8565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b5f33612515858285612bd7565b612520858585612c3b565b506001949350505050565b3361253461167a565b6001600160a01b0316146114615760405163118cdaa760e01b8152336004820152602401610d57565b6060805f6125b8856020013561257286612c98565b61257f60a0890189613da4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612cc392505050565b90935090505f816125ca5760016125cd565b60025b90506125ed6125df60208801886139d8565b8261099560808a018a613da4565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156126925760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061265190899089906004016141f4565b602060405180830381865afa15801561266c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126909190614218565b505b505050509250929050565b604080518082019091525f80825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff1681526020016126ff8961235a565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612734929190614233565b6040805180830381865afa15801561274e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1591906142da565b6001600160a01b03821661279b5760405163ec442f0560e01b81525f6004820152602401610d57565b6127a65f8383612d3d565b5050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00611048565b6004805462010000600160b01b03191690556127ed81612e76565b50565b6127f8612ee6565b6128028383612f0b565b61280b81612f1d565b505050565b6001600160a01b03821661283957604051634b637e8f60e11b81525f6004820152602401610d57565b6127a6825f83612d3d565b5f3361230d818585612c3b565b5f61285f6002828486613fc5565b612868916142f4565b60f01c90506003811461280b578282604051639a6d49cd60e01b8152600401610d57929190614021565b5f8061289f858585612317565b90925090506128ae8683612810565b94509492505050565b6128bf6132af565b5f6128cc845f0151612f3e565b6020850151909150156128e6576128e68460200151612f65565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016129368c61235a565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401612971929190614233565b60806040518083038185885af115801561298d573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906129b2919061432a565b979650505050505050565b5f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156129ff57604051637a02652b60e11b815260040160405180910390fd5b604080515f8082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612a50573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610e1557604051638baa579f60e01b815260040160405180910390fd5b61280b8383836001613044565b5f7f000000000000000000000000000000000000000000000000000000e8d4a51000612abd8184614391565b61104891906143b0565b5f612ad56020828486613fc5565b6123a3916143c7565b5f612aed602860208486613fc5565b612af6916143e4565b60c01c9392505050565b5f6110487f000000000000000000000000000000000000000000000000000000e8d4a510006001600160401b0384166143b0565b5f6001600160a01b038416612b495761dead93505b612b538484612772565b509092915050565b6060612b6a8260288186613fc5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929695505050505050565b606084848484604051602001612bbe949392919061441a565b6040516020818303038152906040529050949350505050565b5f612be284846121b6565b90505f19811015612c355781811015612c2757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610d57565b612c3584848484035f613044565b50505050565b6001600160a01b038316612c6457604051634b637e8f60e11b81525f6004820152602401610d57565b6001600160a01b038216612c8d5760405163ec442f0560e01b81525f6004820152602401610d57565b61280b838383612d3d565b5f6110487f000000000000000000000000000000000000000000000000000000e8d4a5100083614391565b8051606090151580612d0c578484604051602001612cf892919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052612d33565b84843385604051602001612d239493929190614454565b6040516020818303038152906040525b9150935093915050565b5f8051602061449c8339815191526001600160a01b038416612d775781816002015f828254612d6c9190613d73565b90915550612de79050565b6001600160a01b0384165f9081526020829052604090205482811015612dc95760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610d57565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b038316612e05576002810180548390039055612e23565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e6891815260200190565b60405180910390a350505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b612eee613127565b61146157604051631afcd79f60e31b815260040160405180910390fd5b612f13612ee6565b6127a68282613140565b612f25612ee6565b612f2e81613190565b612f366131a1565b6127ed6131a1565b5f813414612f61576040516304fb820960e51b8152346004820152602401610d57565b5090565b5f7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fe69190614480565b90506001600160a01b03811661300f576040516329b99a9560e11b815260040160405180910390fd5b6127a66001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b856131a9565b5f8051602061449c8339815191526001600160a01b03851661307b5760405163e602df0560e01b81525f6004820152602401610d57565b6001600160a01b0384166130a457604051634a1406b160e11b81525f6004820152602401610d57565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115611e8a57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161311891815260200190565b60405180910390a35050505050565b5f6131306127aa565b54600160401b900460ff16919050565b613148612ee6565b5f8051602061449c8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036131818482613c34565b5060048101612c358382613c34565b613198612ee6565b612f2e81613203565b611461612ee6565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612c35908590613214565b61320b612ee6565b6127ed81613280565b5f8060205f8451602086015f885af180613233576040513d5f823e3d81fd5b50505f513d9150811561324a578060011415613257565b6001600160a01b0384163b155b15612c3557604051635274afe760e01b81526001600160a01b0385166004820152602401610d57565b613288612ee6565b6001600160a01b038116611e1857604051632d618d8160e21b815260040160405180910390fd5b60405180606001604052805f80191681526020015f6001600160401b031681526020016132ed60405180604001604052805f81526020015f81525090565b905290565b6001600160a01b03811681146127ed575f80fd5b5f60208284031215613316575f80fd5b81356123a3816132f2565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6123a36020830184613321565b5f8060408385031215613372575f80fd5b823561337d816132f2565b946020939093013593505050565b5f60e0828403121561339b575f80fd5b50919050565b5f602082840312156133b1575f80fd5b81356001600160401b038111156133c6575f80fd5b610c078482850161338b565b83518152602080850151908201525f60a0820160a0604084015280855180835260c08501915060c08160051b8601019250602087015f5b828110156134515760bf19878603018452815180518652602081015190506040602087015261343b6040870182613321565b9550506020938401939190910190600101613409565b50508551606086015250506020840151608084015290506114f8565b5f6060828403121561339b575f80fd5b5f8083601f84011261348d575f80fd5b5081356001600160401b038111156134a3575f80fd5b6020830191508360208285010111156134ba575f80fd5b9250929050565b5f805f805f805f60e0888a0312156134d7575f80fd5b6134e1898961346d565b96506060880135955060808801356001600160401b03811115613502575f80fd5b61350e8a828b0161347d565b90965094505060a0880135613522816132f2565b925060c08801356001600160401b0381111561353c575f80fd5b6135488a828b0161347d565b989b979a50959850939692959293505050565b5f805f6060848603121561356d575f80fd5b8335613578816132f2565b92506020840135613588816132f2565b929592945050506040919091013590565b5f8083601f8401126135a9575f80fd5b5081356001600160401b038111156135bf575f80fd5b6020830191508360208260051b85010111156134ba575f80fd5b5f805f80604085870312156135ec575f80fd5b84356001600160401b03811115613601575f80fd5b61360d87828801613599565b90955093505060208501356001600160401b0381111561362b575f80fd5b61363787828801613599565b95989497509550505050565b803563ffffffff81168114613656575f80fd5b919050565b5f806040838503121561366c575f80fd5b61337d83613643565b80151581146127ed575f80fd5b5f8060408385031215613693575f80fd5b82356001600160401b038111156136a8575f80fd5b6136b48582860161338b565b92505060208301356136c581613675565b809150509250929050565b815181526020808301519082015260408101611048565b803560ff81168114613656575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b038111828210171561372d5761372d6136f7565b60405290565b604051601f8201601f191681016001600160401b038111828210171561375b5761375b6136f7565b604052919050565b5f6001600160401b0382111561377b5761377b6136f7565b50601f01601f191660200190565b5f82601f830112613798575f80fd5b81356137ab6137a682613763565b613733565b8181528460208386010111156137bf575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f80608085870312156137ee575f80fd5b84356137f9816132f2565b9350613807602086016136e7565b925060408501356001600160401b03811115613821575f80fd5b61382d87828801613789565b92505060608501356001600160401b03811115613848575f80fd5b61385487828801613789565b91505092959194509250565b803561ffff81168114613656575f80fd5b5f8060408385031215613882575f80fd5b61388b83613643565b915061389960208401613860565b90509250929050565b5f805f8060a085870312156138b5575f80fd5b6138bf868661346d565b935060608501356001600160401b038111156138d9575f80fd5b6138e58782880161347d565b90945092505060808501356138f9816132f2565b939692955090935050565b60ff60f81b8816815260e060208201525f61392260e0830189613321565b82810360408401526139348189613321565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b8181101561398957835183526020938401939092019160010161396b565b50909b9a5050505050505050505050565b5f80602083850312156139ab575f80fd5b82356001600160401b038111156139c0575f80fd5b6139cc85828601613599565b90969095509350505050565b5f602082840312156139e8575f80fd5b6123a382613643565b5f805f8060608587031215613a04575f80fd5b613a0d85613643565b9350613a1b60208601613860565b925060408501356001600160401b03811115613a35575f80fd5b6136378782880161347d565b5f805f8385036080811215613a54575f80fd5b84356001600160401b03811115613a69575f80fd5b613a758782880161338b565b9450506040601f1982011215613a89575f80fd5b506020840191506060840135613a9e816132f2565b809150509250925092565b5f60c082019050835182526001600160401b0360208501511660208301526040840151613ae3604084018280518252602090810151910152565b5082516080830152602083015160a08301526123a3565b5f805f805f805f60e0888a031215613b10575f80fd5b8735613b1b816132f2565b96506020880135613b2b816132f2565b95506040880135945060608801359350613b47608089016136e7565b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215613b75575f80fd5b8235613b80816132f2565b915060208301356136c5816132f2565b5f60608284031215613ba0575f80fd5b6123a3838361346d565b600181811c90821680613bbe57607f821691505b60208210810361339b57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b601f82111561280b57805f5260205f20601f840160051c81016020851015613c155750805b601f840160051c820191505b81811015611e8a575f8155600101613c21565b81516001600160401b03811115613c4d57613c4d6136f7565b613c6181613c5b8454613baa565b84613bf0565b6020601f821160018114613c93575f8315613c7c5750848201515b5f19600385901b1c1916600184901b178455611e8a565b5f84815260208120601f198516915b82811015613cc25787850151825560209485019460019092019101613ca2565b5084821015613cdf57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f808354613cfb81613baa565b600182168015613d125760018114613d2757613d54565b60ff1983168652811515820286019350613d54565b865f5260205f205f5b83811015613d4c57815488820152600190910190602001613d30565b505081860193505b509195945050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561104857611048613d5f565b5f8235605e19833603018112613d9a575f80fd5b9190910192915050565b5f808335601e19843603018112613db9575f80fd5b8301803591506001600160401b03821115613dd2575f80fd5b6020019150368190038213156134ba575f80fd5b5f60208284031215613df6575f80fd5b6123a382613860565b6001600160401b03831115613e1657613e166136f7565b613e2a83613e248354613baa565b83613bf0565b5f601f841160018114613e5b575f8515613e445750838201355b5f19600387901b1c1916600186901b178355611e8a565b5f83815260208120601f198716915b82811015613e8a5786850135825560209485019460019092019101613e6a565b5086821015613ea6575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602080825281018290525f6040600584901b830181019083018583605e1936839003015b87821015613fb857868503603f190184528235818112613f22575f80fd5b890163ffffffff613f3282613643565b16865261ffff613f4460208301613860565b1660208701526040810135601e19823603018112613f60575f80fd5b016020810190356001600160401b03811115613f7a575f80fd5b803603821315613f88575f80fd5b60606040880152613f9d606088018284613eb8565b96505050602083019250602084019350600182019150613f04565b5092979650505050505050565b5f8085851115613fd3575f80fd5b83861115613fdf575f80fd5b5050820193919092039150565b5f81518060208401855e5f93019283525090919050565b5f61400e8286613fec565b838582375f930192835250909392505050565b602081525f6114f8602083018486613eb8565b5f823561013e19833603018112613d9a575f80fd5b6001600160401b03811681146127ed575f80fd5b63ffffffff61406b89613643565b168152602088810135908201525f604089013561408781614049565b6001600160401b03811660408401525087606083015260e060808301526140b260e083018789613eb8565b6001600160a01b03861660a084015282810360c08401526140d4818587613eb8565b9a9950505050505050505050565b5f602082840312156140f2575f80fd5b81516001600160401b03811115614107575f80fd5b8201601f81018413614117575f80fd5b80516141256137a682613763565b818152856020838501011115614139575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b5f6040828403128015614167575f80fd5b5061417061370b565b823581526020928301359281019290925250919050565b5f6001820161419857614198613d5f565b5060010190565b5f602082840312156141af575f80fd5b81356123a381614049565b60018060a01b038516815283602082015261ffff83166040820152608060608201525f6141ea6080830184613321565b9695505050505050565b604081525f6142066040830185613321565b8281036020840152610e158185613321565b5f60208284031215614228575f80fd5b81516123a381613675565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a0608084015261426860e0840182613321565b90506060850151603f198483030160a08501526142858282613321565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f604082840312156142bb575f80fd5b6142c361370b565b825181526020928301519281019290925250919050565b5f604082840312156142ea575f80fd5b6123a383836142ab565b80356001600160f01b03198116906002841015610c0a576001600160f01b031960029490940360031b84901b1690921692915050565b5f608082840312801561433b575f80fd5b50604051606081016001600160401b038111828210171561435e5761435e6136f7565b60405282518152602083015161437381614049565b602082015261438584604085016142ab565b60408201529392505050565b5f826143ab57634e487b7160e01b5f52601260045260245ffd5b500490565b808202811582820484141761104857611048613d5f565b80356020831015611048575f19602084900360031b1b1692915050565b80356001600160c01b03198116906008841015610c0a576001600160c01b031960089490940360031b84901b1690921692915050565b60c085901b6001600160c01b031916815260e084901b6001600160e01b0319166008820152600c81018390525f6141ea602c830184613fec565b8481526001600160401b0360c01b8460c01b1660208201528260288201525f6141ea6048830184613fec565b5f60208284031215614490575f80fd5b81516123a3816132f256fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220b28d93f9c39f9e9b08eb020938d3ac2d50af7b10d52d8d6f49e5928cf6700b5864736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
-----Decoded View---------------
Arg [0] : _lzEndpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode Sourcemap
174868:6905:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175499:40;;;;;;;;;;-1:-1:-1;175499:40:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;567:14:1;;560:22;542:41;;530:2;515:18;175499:40:0;;;;;;;;69383:147;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;181569:201::-;;;;;;;;;;-1:-1:-1;181569:201:0;;;;;:::i;:::-;;:::i;146880:1283::-;;;;;;;;;;-1:-1:-1;146880:1283:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;145122:152::-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;3636:32:1;;;3618:51;;3606:2;3591:18;145122:152:0;3472:203:1;113736:723:0;;;;;;:::i;:::-;;:::i;:::-;;143051:40;;;;;;;;;;;;143090:1;143051:40;;;;;5465:6:1;5453:19;;;5435:38;;5423:2;5408:18;143051:40:0;5291:188:1;144291:142:0;;;;;;;;;;-1:-1:-1;144291:142:0;;;-1:-1:-1;;;5654:52:1;;144423:1:0;5737:2:1;5722:18;;5715:59;5627:18;144291:142:0;5484:296:1;140771:265:0;;;;;;;;;;-1:-1:-1;140771:265:0;;;133638:1;5955:50:1;;109486:1:0;6036:2:1;6021:18;;6014:59;5928:18;140771:265:0;5785:294:1;70597:155:0;;;;;;;;;;-1:-1:-1;70730:14:0;;70597:155;;;6230:25:1;;;6218:2;6203:18;70597:155:0;6084:177:1;143013:31:0;;;;;;;;;;;;143043:1;143013:31;;181336:225;;;;;;;;;;-1:-1:-1;181336:225:0;;;;;:::i;:::-;;:::i;178946:425::-;;;;;;;;;;-1:-1:-1;178946:425:0;;;;;:::i;:::-;;:::i;166481:137::-;;;;;;;;;;;;166523:95;166481:137;;172397:161;;;;;;;;;;;;;:::i;:::-;;;8278:4:1;8266:17;;;8248:36;;8236:2;8221:18;172397:161:0;8106:184:1;99703:206:0;;;;;;;;;;-1:-1:-1;99703:206:0;;;;;:::i;:::-;;:::i;172010:111::-;;;;;;;;;;-1:-1:-1;172097:16:0;;172010:111;;148626:787;;;;;;;;;;-1:-1:-1;148626:787:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;179573:140::-;;;;;;;;;;-1:-1:-1;179573:140:0;;;;;:::i;:::-;;:::i;177780:973::-;;;;;;;;;;-1:-1:-1;177780:973:0;;;;;:::i;:::-;;:::i;128348:95::-;;;;;;;;;;-1:-1:-1;128430:4:0;128348:95;;63155:225;;;;;;;;;;-1:-1:-1;63155:225:0;;;;;:::i;:::-;;:::i;157108:134::-;;;;;;;;;;-1:-1:-1;157108:134:0;;;;;:::i;:::-;99147:13;;;;;157190:4;99147:13;;;-1:-1:-1;;;;;;;;;;;99147:13:0;;;;;;157214:20;;157108:134;97663:46;;;;;;;;;;;;;;;146339:226;;;;;;;;;;-1:-1:-1;146339:226:0;;;;;:::i;:::-;;:::i;70815:174::-;;;;;;;;;;-1:-1:-1;70815:174:0;;;;;:::i;:::-;-1:-1:-1;;;;;70961:20:0;70880:7;70961:20;;;-1:-1:-1;;;;;;;;;;;70961:20:0;;;;;;;70815:174;53974:103;;;;;;;;;;;;;:::i;170199:182::-;;;;;;;;;;;;;:::i;112858:130::-;;;;;;;;;;-1:-1:-1;112858:130:0;;;;;:::i;:::-;112947:12;112858:130;;;;;;;;-1:-1:-1;;;;;12955:31:1;;;12937:50;;12925:2;12910:18;112858:130:0;12793:200:1;172129:116:0;;;;;;;;;;-1:-1:-1;172129:116:0;;;;;:::i;:::-;-1:-1:-1;;;;;172218:19:0;172191:7;172218:19;;;:13;:19;;;;;;;172129:116;111332:222;;;;;;;;;;-1:-1:-1;111332:222:0;;;;;:::i;:::-;;:::i;171149:663::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;145893:89::-;;;;;;;;;;-1:-1:-1;145973:1:0;145893:89;;53239:147;;;;;;;;;;;;;:::i;69649:151::-;;;;;;;;;;;;;:::i;142702:46::-;;;;;;;;;;;;;;;179886:140;;;;;;;;;;-1:-1:-1;179886:140:0;;;;;:::i;:::-;;:::i;163343:96::-;;;;;;;;;;-1:-1:-1;163402:4:0;163343:96;;181135:193;;;;;;;;;;-1:-1:-1;181135:193:0;;;;;:::i;:::-;;:::i;180221:255::-;;;;;;;;;;-1:-1:-1;180221:255:0;;;;;:::i;:::-;;:::i;127864:183::-;;;;;;;;;;;;;:::i;64151:609::-;;;;;;;;;;-1:-1:-1;64151:609:0;;;;;:::i;:::-;;:::i;99002:166::-;;;;;;;;;;-1:-1:-1;99002:166:0;;;;;:::i;:::-;99147:13;;99060:7;99147:13;;;-1:-1:-1;;;;;;;;;;;99147:13:0;;;;;;;99002:166;65533:1081;;;;;;;;;;-1:-1:-1;65533:1081:0;;;;;:::i;:::-;;:::i;129280:1358::-;;;;;;:::i;:::-;;:::i;150118:1364::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;100824:107::-;;;;;;;;;;-1:-1:-1;100824:107:0;;;;;:::i;:::-;;:::i;180621:316::-;;;;;;;;;;-1:-1:-1;180621:316:0;;;;;:::i;:::-;;:::i;131300:419::-;;;;;;:::i;:::-;;:::i;128581:230::-;;;;;;;;;;-1:-1:-1;128581:230:0;;;;;:::i;:::-;;:::i;168507:1041::-;;;;;;;;;;-1:-1:-1;168507:1041:0;;;;;:::i;:::-;;:::i;71439:198::-;;;;;;;;;;-1:-1:-1;71439:198:0;;;;;:::i;:::-;;:::i;170936:95::-;;;;;;;;;;-1:-1:-1;171010:13:0;;;;;-1:-1:-1;;;;;171010:13:0;170936:95;;169809:268;;;;;;;;;;-1:-1:-1;169809:268:0;;;;;:::i;:::-;;:::i;175386:40::-;;;;;;;;;;-1:-1:-1;175386:40:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;112107:151;;;;;;;;;;-1:-1:-1;112107:151:0;;;;;:::i;:::-;;:::i;69383:147::-;69515:7;69508:14;;69428:13;;-1:-1:-1;;;;;;;;;;;68728:20:0;69508:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69383:147;:::o;181569:201::-;181687:10;181708:4;177256:17;;;:5;:17;;;;;;181708:4;;181687:10;177238:15;:35;177234:62;;;177282:14;;-1:-1:-1;;;177282:14:0;;;;;;;;;;;177234:62;181732:30:::1;181746:7;181755:6;181732:13;:30::i;:::-;181725:37;;177307:1;181569:201:::0;;;;;:::o;146880:1283::-;-1:-1:-1;;;;;;;;;;;;;;;;;147038:35:0;147075:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;147075:28:0;147297:34;;;;;;;;-1:-1:-1;147297:34:0;;;-1:-1:-1;;;;;147297:34:0;;;;;;;147451:21;;;;;;;;;;;147297:34;;-1:-1:-1;;;147451:21:0;;;-1:-1:-1;;;;;;;;;;;;;;;;;147451:21:0;;;;;;;;;;;;;;;-1:-1:-1;147435:37:0;-1:-1:-1;147915:20:0;;147965:124;147990:19;;;;148024:22;;;;148061:17;;;;147990:10;148061:17;:::i;:::-;147965:10;:124::i;:::-;148113:42;;;;;;;;;;;;;;;;146880:1283;;;;-1:-1:-1;;;;;;146880:1283:0:o;145122:152::-;145167:7;;143273:25;145214:20;145252:14;-1:-1:-1;;;;;145252:14:0;;145122:152;-1:-1:-1;;145122:152:0:o;113736:723::-;114057:8;-1:-1:-1;;;;;114049:31:0;114070:10;114049:31;114045:68;;114089:24;;-1:-1:-1;;;114089:24:0;;114102:10;114089:24;;;3618:51:1;3591:18;;114089:24:0;;;;;;;;114045:68;114252:14;;;;;;114216:32;;114233:14;;114252:7;114233:14;:::i;:::-;114216:16;:32::i;:::-;:50;114212:103;;114284:14;;;;:7;:14;:::i;:::-;114275:40;;-1:-1:-1;;;114275:40:0;;20066:10:1;20054:23;;;114275:40:0;;;20036:42:1;114300:14:0;;;;20094:18:1;;;20087:34;20009:18;;114275:40:0;19864:263:1;114212:103:0;114392:59;114403:7;114412:5;114419:8;;114429:9;114440:10;;114392;:59::i;:::-;113736:723;;;;;;;:::o;181336:225::-;-1:-1:-1;;;;;177256:17:0;;181493:4;177256:17;;;:5;:17;;;;;;181478:4;;177238:15;:35;177234:62;;;177282:14;;-1:-1:-1;;;177282:14:0;;;;;;;;;;;177234:62;181517:36:::1;181536:4;181542:2;181546:6;181517:18;:36::i;:::-;181510:43:::0;181336:225;-1:-1:-1;;;;;181336:225:0:o;178946:425::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168322:11:::1;::::0;::::1;;168318:43;;;168342:19;;-1:-1:-1::0;;;168342:19:0::1;;;;;;;;;;;168318:43;53125:13:::2;:11;:13::i;:::-;179121:11:::3;:18:::0;;-1:-1:-1;;179121:18:0::3;179135:4;179121:18;::::0;;:11:::3;179152:100;179168:21:::0;;::::3;179152:100;;;179236:4;179211:7;:22;179219:10;;179230:1;179219:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;179211:22:0::3;::::0;;::::3;::::0;::::3;::::0;;;;;;-1:-1:-1;179211:22:0;:29;;-1:-1:-1;;179211:29:0::3;::::0;::::3;;::::0;;;::::3;::::0;;-1:-1:-1;179191:3:0::3;179152:100;;;;179269:9;179264:100;179280:21:::0;;::::3;179264:100;;;179348:4;179323:7;:22;179331:10;;179342:1;179331:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;179323:22:0::3;::::0;;::::3;::::0;::::3;::::0;;;;;;-1:-1:-1;179323:22:0;:29;;-1:-1:-1;;179323:29:0::3;::::0;::::3;;::::0;;;::::3;::::0;;-1:-1:-1;179303:3:0::3;179264:100;;;-1:-1:-1::0;;2702:1:0;4334:7;:22;-1:-1:-1;;;178946:425:0:o;172397:161::-;172481:14;;172455:5;;172504:1;172481:14;;;;:25;:14;:25;172480:70;;-1:-1:-1;172536:14:0;;;;;;;;172397:161::o;172480:70::-;-1:-1:-1;166728:2:0;;172397:161::o;99703:206::-;53125:13;:11;:13::i;:::-;99844::::1;::::0;::::1;99784:25;99844:13:::0;;;-1:-1:-1;;;;;;;;;;;99844:13:0::1;::::0;;;;;;;;:21;;;99881:20;;20036:42:1;;;20094:18;;20087:34;;;97549:26:0;99881:20:::1;::::0;20009:18:1;99881:20:0::1;;;;;;;;99773:136;99703:206:::0;;:::o;148626:787::-;-1:-1:-1;;;;;;;;;;;;;;;;;148966:24:0;148994:74;149005:19;;;;149026:22;;;;149050:17;;;;149005:10;149050:17;:::i;148994:74::-;148963:105;;;149160:20;149182;149206:49;149226:10;149238:16;149206:19;:49::i;:::-;149159:96;;-1:-1:-1;149159:96:0;-1:-1:-1;149347:58:0;149354:17;;;;:10;:17;:::i;:::-;149373:7;149382;149391:13;149347:6;:58::i;:::-;149340:65;;;;;148626:787;;;;;:::o;179573:140::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;176863:10:::2;176855:19;::::0;;;:7:::2;:19;::::0;;;;;::::2;;176850:53;;176883:20;;-1:-1:-1::0;;;176883:20:0::2;;;;;;;;;;;176850:53;179686:19:::3;179692:4;179698:6;179686:5;:19::i;:::-;-1:-1:-1::0;;2702:1:0;4334:7;:22;179573:140::o;177780:973::-;26771:30;26804:26;:24;:26::i;:::-;26918:15;;26771:59;;-1:-1:-1;26918:15:0;-1:-1:-1;;;26918:15:0;;;26917:16;;-1:-1:-1;;;;;26965:14:0;26895:19;27348:16;;:34;;;;;27368:14;27348:34;27328:54;;27393:17;27413:11;-1:-1:-1;;;;;27413:16:0;27428:1;27413:16;:50;;;;-1:-1:-1;27441:4:0;27433:25;:30;27413:50;27393:70;;27481:12;27480:13;:30;;;;;27498:12;27497:13;27480:30;27476:93;;;27534:23;;-1:-1:-1;;;27534:23:0;;;;;;;;;;;27476:93;27579:18;;-1:-1:-1;;27579:18:0;27596:1;27579:18;;;27608:69;;;;27643:22;;-1:-1:-1;;;;27643:22:0;-1:-1:-1;;;27643:22:0;;;27608:69;177990:8:::1;-1:-1:-1::0;;;;;177982:31:0::1;177978:70;;178022:26;;-1:-1:-1::0;;;178022:26:0::1;;;;;;;;;;;177978:70;178061:11;:23;178075:9:::0;178061:11;:23:::1;:::i;:::-;-1:-1:-1::0;178095:20:0::1;::::0;;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;178095:20:0::1;::::0;::::1;::::0;:14:::1;::::0;:20:::1;::::0;:14;:20:::1;:::i;:::-;;166379:95;178262:11;178246:29;;;;;;:::i;:::-;;;;;;;;178327:14;178311:32;;;;;;:::i;:::-;;::::0;;;;;::::1;::::0;;178155:316:::1;::::0;::::1;23451:25:1::0;;;;23492:18;;23485:34;;;;23535:18;;;23528:34;;;;178378:13:0::1;23578:18:1::0;;;23571:34;178435:4:0::1;23621:19:1::0;;;23614:61;23423:19;;178155:316:0::1;::::0;;;;::::1;-1:-1:-1::0;;178155:316:0;;;;;;178145:327;;178155:316:::1;178145:327:::0;;::::1;::::0;178126:16:::1;:346:::0;178485:14:::1;:30:::0;;-1:-1:-1;;178485:30:0::1;;;::::0;::::1;;;::::0;;178621:32:::1;178640:12:::0;178621:18:::1;:32::i;:::-;178697:48;178708:9;178719:11;178732:12;178697:10;:48::i;:::-;27703:14:::0;27699:104;;;27734:23;;-1:-1:-1;;;;27734:23:0;;;27777:14;;-1:-1:-1;12937:50:1;;27777:14:0;;12925:2:1;12910:18;27777:14:0;;;;;;;27699:104;26703:1107;;;;;177780:973;;;;:::o;63155:225::-;63339:23;;;63256:33;63339:23;;;62762:36;63339:23;;;;;;;;:33;;;;;;;;;;;63332:40;;63231:12;;62762:36;63339:33;63332:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63155:225;;;;:::o;146339:226::-;53125:13;:11;:13::i;:::-;143273:25;146481:30;;-1:-1:-1;;;;;;146481:30:0::1;-1:-1:-1::0;;;;;146481:30:0;::::1;::::0;;::::1;::::0;;146527::::1;::::0;3618:51:1;;;146527:30:0::1;::::0;3606:2:1;3591:18;146527:30:0::1;;;;;;;;146412:153;146339:226:::0;:::o;53974:103::-;53125:13;:11;:13::i;:::-;54039:30:::1;54066:1;54039:18;:30::i;:::-;53974:103::o:0;170199:182::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;170282:13:::2;::::0;;;::::2;-1:-1:-1::0;;;;;170282:13:0::2;170299:10;170282:27;170278:54;;170318:14;;-1:-1:-1::0;;;170318:14:0::2;;;;;;;;;;;170278:54;170343:30;170362:10;170343:18;:30::i;:::-;2702:1:::0;4334:7;:22;170199:182::o;111332:222::-;-1:-1:-1;;;;;111522:24:0;;111541:4;111522:24;111332:222;;;;;;;:::o;171149:663::-;171215:13;171239:24;171274:27;171312:15;171338:25;171374:12;171397:27;171540:1;171532:10;;171512:16;;:30;171508:67;;171551:24;;-1:-1:-1;;;171551:24:0;;;;;;;;;;;171508:67;171777:16;;;171760:1;171777:16;;;;;;;;;171641:11;171588:216;;-1:-1:-1;;;171588:216:0;171641:11;;171667:14;;171696:13;;171732:4;;171777:16;171641:11;;171588:216;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;171149:663;;;;;;;:::o;53239:147::-;53285:7;;52070:22;53332:20;51947:163;69649:151;69783:9;69776:16;;69696:13;;-1:-1:-1;;;;;;;;;;;68728:20:0;69776:16;;;:::i;179886:140::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;177037:10:::2;177029:19;::::0;;;:7:::2;:19;::::0;;;;;::::2;;177024:53;;177057:20;;-1:-1:-1::0;;;177057:20:0::2;;;;;;;;;;;177024:53;179999:19:::3;180005:4;180011:6;179999:5;:19::i;181135:193::-:0;181249:10;181270:4;177256:17;;;:5;:17;;;;;;181270:4;;181249:10;177238:15;:35;177234:62;;;177282:14;;-1:-1:-1;;;177282:14:0;;;;;;;;;;;177234:62;181294:26:::1;181309:2;181313:6;181294:14;:26::i;180221:255::-:0;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;53125:13:::2;:11;:13::i;:::-;180391:23:::3;:10:::0;180404::::3;180391:23;:::i;:::-;-1:-1:-1::0;;;;;180371:17:0;::::3;;::::0;;;:5:::3;:17;::::0;;;;;;;;:43;;;;180430:38;;24336:51:1;;;24403:18;;;24396:34;;;180430:38:0::3;::::0;24309:18:1;180430:38:0::3;;;;;;;-1:-1:-1::0;;2702:1:0;4334:7;:22;180221:255::o;127864:183::-;127916:7;;127456:41;127977:34;127304:211;64151:609;53125:13;:11;:13::i;:::-;62762:36;64264:33:::1;64340:360;64360:27:::0;;::::1;64340:360;;;64524:48;64544:16;;64561:1;64544:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;64524:19;:48::i;:::-;64661:16;;64678:1;64661:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;64587:1:::0;:17:::1;64605:16:::0;;64622:1;64605:19;;::::1;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:23;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;64587:42;;;;;;;;;;;;;;;:71;64630:16;;64647:1;64630:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;;;;;::::1;;;:::i;:::-;64587:71;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;64587:71:0;;:101:::1;::::0;;:71;:101:::1;:::i;:::-;-1:-1:-1::0;64389:3:0::1;;64340:360;;;;64717:35;64735:16;;64717:35;;;;;;;:::i;65533:1081::-:0;65805:23;;;65705:33;65805:23;;;62762:36;65805:23;;;;;;;;:33;;;;;;;;;;65781:57;;65680:12;;65705:33;65805;65781:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65970:8;:15;65989:1;65970:20;65966:46;;65999:13;;65992:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65992:20:0;;-1:-1:-1;65992:20:0;;-1:-1:-1;;;;;65992:20:0;65966:46;66100:1;66076:25;;;66072:46;;66110:8;-1:-1:-1;66103:15:0;;-1:-1:-1;66103:15:0;66072:46;66268:1;66244:25;;66240:271;;66286:34;66306:13;;66286:19;:34::i;:::-;66471:8;66481:17;:13;66495:1;66481:13;;:17;:::i;:::-;66458:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;66451:48;;;;;;66240:271;66592:13;;66577:29;;-1:-1:-1;;;66577:29:0;;;;;;;;;:::i;129280:1358::-;129382:9;129377:1057;129397:19;;;129377:1057;;;129438:29;129470:8;;129479:1;129470:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;129438:43;-1:-1:-1;129567:50:0;129574:20;;;;129438:43;129574:20;:::i;:::-;129596;;;;99147:13;;;;;157190:4;99147:13;;;-1:-1:-1;;;;;;;;;;;99147:13:0;;;;;;157214:20;;157108:134;129567:50;129562:65;;129619:8;;;129562:65;130198:4;:22;130229:12;;;;:6;130294:11;;;;130324:14;;;;130229:6;130324:14;:::i;:::-;130357:15;;;;;;;;:::i;:::-;130391:16;;;;:6;:16;:::i;:::-;130198:224;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129423:1011;129377:1057;129418:3;;129377:1057;;;;130594:10;-1:-1:-1;;;;;130584:43:0;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;130584:45:0;;;;;;;;;;;;:::i;:::-;130567:63;;-1:-1:-1;;;130567:63:0;;;;;;;;:::i;150118:1364::-;150283:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;150685:20:0;;150735:145;150756:10;150781:19;;;;150815:22;;;;150852:17;;;;150781:10;150852:17;:::i;:::-;150735:6;:145::i;:::-;150684:196;;;;150972:20;150994;151018:49;151038:10;151050:16;151018:19;:49::i;:::-;150971:96;;-1:-1:-1;150971:96:0;-1:-1:-1;151193:66:0;151201:17;;;;:10;:17;:::i;:::-;151220:7;151229;151193:66;;;;;;;151238:4;151193:66;:::i;:::-;151244:14;151193:7;:66::i;:::-;151327:42;;;;;;;;;;;;;;;;;;;151395:15;;151180:79;;-1:-1:-1;151327:42:0;;-1:-1:-1;151431:10:0;;151395:15;151387:87;;151412:17;;;;:10;:17;:::i;:::-;151387:87;;;32810:10:1;32798:23;;;32780:42;;32853:2;32838:18;;32831:34;;;32881:18;;32874:34;;;32768:2;32753:18;151387:87:0;;;;;;;150349:1133;;;;150118:1364;;;;;;:::o;100824:107::-;53125:13;:11;:13::i;:::-;100892:31:::1;::::0;-1:-1:-1;;;100892:31:0;;-1:-1:-1;;;;;3636:32:1;;;100892:31:0::1;::::0;::::1;3618:51:1::0;100892:8:0::1;:20;::::0;::::1;::::0;3591:18:1;;100892:31:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;100824:107:::0;:::o;180621:316::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;53125:13:::2;:11;:13::i;:::-;-1:-1:-1::0;;;;;180731:17:0;::::3;;::::0;;;:5:::3;:17;::::0;;;;;180751:1:::3;-1:-1:-1::0;180727:48:0::3;;;180761:14;;-1:-1:-1::0;;;180761:14:0::3;;;;;;;;;;;180727:48;-1:-1:-1::0;;;;;180808:17:0;::::3;;::::0;;;:5:::3;:17;::::0;;;;;180790:15:::3;:35;180786:62;;;180834:14;;-1:-1:-1::0;;;180834:14:0::3;;;;;;;;;;;180786:62;-1:-1:-1::0;;;;;180868:17:0;::::3;;::::0;;;:5:::3;:17;::::0;;;;;;;180861:24;;;;180901:28;;3618:51:1;;;180901:28:0::3;::::0;3591:18:1;180901:28:0::3;;;;;;;-1:-1:-1::0;2702:1:0;4334:7;:22;180621:316::o;131300:419::-;131587:10;131609:4;131587:27;131583:50;;131623:10;;-1:-1:-1;;;131623:10:0;;;;;;;;;;;131583:50;131644:67;131663:7;131672:5;131679:8;;131689:9;131700:10;;131644:18;:67::i;128581:230::-;53125:13;:11;:13::i;:::-;127456:41;128743:22;;-1:-1:-1;;;;;;128743:22:0::1;-1:-1:-1::0;;;;;128743:22:0;::::1;::::0;;::::1;::::0;;128781::::1;::::0;3618:51:1;;;128781:22:0::1;::::0;3606:2:1;3591:18;128781:22:0::1;3472:203:1::0;168507:1041:0;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168755:15:::1;168744:26:::0;::::1;168740:56;;;168779:17;;-1:-1:-1::0;;;168779:17:0::1;;;;;;;;;;;168740:56;168893:16;::::0;-1:-1:-1;;;;;169123:25:0;;::::1;168850:9;169123:25:::0;;;:13:::1;:25;::::0;;;;;;;;168953:246;;166523:95:::1;168953:246:::0;;::::1;33206:25:1::0;33247:18;;;33240:60;;;;33336:32;;;33316:18;;;33309:60;33385:18;;;33378:34;;;33428:19;;;33421:35;;;;33472:19;;;;33465:35;;;168953:246:0;;;;;;;;;;33178:19:1;;;168953:246:0;;;;168925:289;;;::::1;::::0;-1:-1:-1;;;174515:23:0;;174559:14;;;174552:45;;;;174618:14;;;;174611:34;;;;174682:4;174667:20;;;169300::::1;174667::::0;169312:1;169315;169318;169300:8:::1;:20::i;:::-;169283:37;;169345:10;-1:-1:-1::0;;;;;169335:20:0::1;:6;-1:-1:-1::0;;;;;169335:20:0::1;;169331:48;;169364:15;;-1:-1:-1::0;;;169364:15:0::1;;;;;;;;;;;169331:48;-1:-1:-1::0;;;;;169424:25:0;::::1;;::::0;;;:13:::1;:25;::::0;;;;:27;;;::::1;::::0;::::1;:::i;:::-;;;;;;169500:40;169509:10;169521:11;169534:5;169500:8;:40::i;:::-;-1:-1:-1::0;;2702:1:0;4334:7;:22;-1:-1:-1;;;;;;;168507:1041:0:o;71439:198::-;-1:-1:-1;;;;;71600:20:0;;;71519:7;71600:20;;;:13;:20;;;;;;;;:29;;;;;;;;;;;;;71439:198::o;169809:268::-;2746:1;4020:7;;:19;4016:74;;4063:15;;-1:-1:-1;;;4063:15:0;;;;;;;;;;;4016:74;2746:1;4167:7;:18;168217:11:::1;::::0;::::1;;168212:40;;168237:15;;-1:-1:-1::0;;;168237:15:0::1;;;;;;;;;;;168212:40;53125:13:::2;:11;:13::i;:::-;-1:-1:-1::0;;;;;169929:22:0;::::3;169925:48;;169960:13;;-1:-1:-1::0;;;169960:13:0::3;;;;;;;;;;;169925:48;169986:13;:24:::0;;-1:-1:-1;;;;;;169986:24:0::3;::::0;-1:-1:-1;;;;;169986:24:0;::::3;::::0;;::::3;::::0;;;::::3;::::0;;;170051:7:::3;:5;:7::i;:::-;-1:-1:-1::0;;;;;170026:43:0::3;;;;;;;;;;;-1:-1:-1::0;2702:1:0;4334:7;:22;169809:268::o;112107:151::-;112189:4;112237:13;;;;;;112213:20;;112219:13;;112237:6;112219:13;:::i;112213:20::-;:37;;112107:151;-1:-1:-1;;112107:151:0:o;71956:190::-;72029:4;45765:10;72085:31;45765:10;72101:7;72110:5;72085:8;:31::i;:::-;-1:-1:-1;72134:4:0;;71956:190;-1:-1:-1;;;71956:190:0:o;159169:682::-;159315:20;159337:24;159513:22;159525:9;159513:11;:22::i;:::-;159498:37;;159663:12;159644:31;;159748:12;159729:16;:31;159725:119;;;159784:48;;-1:-1:-1;;;159784:48:0;;;;;33825:25:1;;;33866:18;;;33859:34;;;33798:18;;159784:48:0;33651:248:1;159725:119:0;159169:682;;;;;;:::o;100215:262::-;100380:13;;;100285:7;100380:13;;;-1:-1:-1;;;;;;;;;;;100380:13:0;;;;;;;;;100404:43;;100435:12;;-1:-1:-1;;;100435:12:0;;34078:10:1;34066:23;;100435:12:0;;;34048:42:1;34021:18;;100435:12:0;33904:192:1;100404:43:0;100465:4;100215:262;-1:-1:-1;;;100215:262:0:o;153836:1837::-;154322:17;154342:36;:17;:8;;:15;:17::i;:::-;38083:2;37971:125;154342:36;154322:56;;154513:24;154540:62;154548:9;154559:26;154565:19;:8;;:17;:19::i;:::-;154559:5;:26::i;:::-;154587:14;;;;:7;:14;:::i;:::-;154540:7;:62::i;:::-;154513:89;-1:-1:-1;35362:2:0;-1:-1:-1;;154615:970:0;;;154721:23;154747:180;154791:13;;;;;;;;:::i;:::-;154823:14;;;;:7;:14;:::i;:::-;154856:16;154891:21;:8;;:19;:21::i;:::-;154747:25;:180::i;:::-;155481:92;;-1:-1:-1;;;155481:92:0;;154721:206;;-1:-1:-1;;;;;;155481:8:0;:20;;;;:92;;155502:9;;155513:5;;155520:1;;154721:206;;155481:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;154642:943;154615:970;-1:-1:-1;;;;;155602:63:0;;155614:5;155602:63;155621:14;;;;:7;:14;:::i;:::-;155602:63;;;20066:10:1;20054:23;;;20036:42;;20109:2;20094:18;;20087:34;;;20009:18;155602:63:0;;;;;;;154145:1528;;153836:1837;;;;;;;:::o;72756:249::-;72843:4;45765:10;72901:37;72917:4;45765:10;72932:5;72901:15;:37::i;:::-;72949:26;72959:4;72965:2;72969:5;72949:9;:26::i;:::-;-1:-1:-1;72993:4:0;;72756:249;-1:-1:-1;;;;72756:249:0:o;53464:166::-;45765:10;53524:7;:5;:7::i;:::-;-1:-1:-1;;;;;53524:23:0;;53520:103;;53571:40;;-1:-1:-1;;;53571:40:0;;45765:10;53571:40;;;3618:51:1;3591:18;;53571:40:0;3472:203:1;151785:1520:0;151920:20;151942;151975:15;152148:330;152181:10;:13;;;152209:16;152215:9;152209:5;:16::i;:::-;152446:21;;;;:10;:21;:::i;:::-;152148:330;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;152148:18:0;;-1:-1:-1;;;152148:330:0:i;:::-;152124:354;;-1:-1:-1;152124:354:0;-1:-1:-1;152560:14:0;152124:354;152577:33;;143043:1;152577:33;;;143090:1;152577:33;152560:50;-1:-1:-1;152734:67:0;152749:17;;;;:10;:17;:::i;:::-;152768:7;152777:23;;;;:10;:23;:::i;152734:67::-;143273:25;153123:14;;152724:77;;-1:-1:-1;143273:25:0;-1:-1:-1;;;;;153123:14:0;153218:23;;153214:83;;153243:54;;-1:-1:-1;;;153243:54:0;;-1:-1:-1;;;;;153243:36:0;;;;;:54;;153280:7;;153289;;153243:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;153214:83;151964:1341;;;;151785:1520;;;;;:::o;135337:402::-;-1:-1:-1;;;;;;;;;;;;;;;;;135565:8:0;-1:-1:-1;;;;;135565:14:0;;135598:86;;;;;;;;135614:7;135598:86;;;;;;135623:25;135640:7;135623:16;:25::i;:::-;135598:86;;;;135650:8;135598:86;;;;135660:8;135598:86;;;;135670:13;135598:86;;;;;135711:4;135565:166;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;75574:213::-;-1:-1:-1;;;;;75645:21:0;;75641:93;;75690:32;;-1:-1:-1;;;75690:32:0;;75719:1;75690:32;;;3618:51:1;3591:18;;75690:32:0;3472:203:1;75641:93:0;75744:35;75760:1;75764:7;75773:5;75744:7;:35::i;:::-;75574:213;;:::o;31810:210::-;31868:30;;25731:66;31926:27;31550:124;170571:156;170661:13;170654:20;;-1:-1:-1;;;;;;170654:20:0;;;170685:34;170710:8;170685:24;:34::i;:::-;170571:156;:::o;162454:192::-;29607:20;:18;:20::i;:::-;162574:28:::1;162587:5;162594:7;162574:12;:28::i;:::-;162613:25;162628:9;162613:14;:25::i;:::-;162454:192:::0;;;:::o;76115:211::-;-1:-1:-1;;;;;76186:21:0;;76182:91;;76231:30;;-1:-1:-1;;;76231:30:0;;76258:1;76231:30;;;3618:51:1;3591:18;;76231:30:0;3472:203:1;76182:91:0;76283:35;76291:7;76308:1;76312:5;76283:7;:35::i;71194:182::-;71263:4;45765:10;71319:27;45765:10;71336:2;71340:5;71319:9;:27::i;66760:221::-;66847:18;66882:13;66893:1;66847:18;66882:8;;:13;:::i;:::-;66875:21;;;:::i;:::-;66868:29;;;-1:-1:-1;62610:1:0;66912:28;;66908:65;;66964:8;;66949:24;;-1:-1:-1;;;66949:24:0;;;;;;;;;:::i;163933:580::-;164099:20;164121:24;164193:44;164204:9;164215:12;164229:7;164193:10;:44::i;:::-;164158:79;;-1:-1:-1;164158:79:0;-1:-1:-1;164479:26:0;164485:5;164158:79;164479:5;:26::i;:::-;163933:580;;;;;;;:::o;136514:783::-;136721:31;;:::i;:::-;136888:20;136911:26;136922:4;:14;;;136911:10;:26::i;:::-;136952:15;;;;136888:49;;-1:-1:-1;136952:19:0;136948:53;;136973:28;136985:4;:15;;;136973:11;:28::i;:::-;137094:8;-1:-1:-1;;;;;137094:13:0;;137116:12;137149:92;;;;;;;;137165:7;137149:92;;;;;;137174:25;137191:7;137174:16;:25::i;:::-;137149:92;;;;137201:8;137149:92;;;;137211:8;137149:92;;;;137239:1;137221:4;:15;;;:19;137149:92;;;;;137260:14;137094:195;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137014:275;136514:783;-1:-1:-1;;;;;;;136514:783:0:o;172566:1370::-;172652:7;173572:66;173559:79;;173555:147;;;173662:28;;-1:-1:-1;;;173662:28:0;;;;;;;;;;;173555:147;173816:24;;;173799:14;173816:24;;;;;;;;;38590:25:1;;;38663:4;38651:17;;38631:18;;;38624:45;;;;38685:18;;;38678:34;;;38728:18;;;38721:34;;;173816:24:0;;38562:19:1;;173816:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;173816:24:0;;-1:-1:-1;;173816:24:0;;;-1:-1:-1;;;;;;;173855:20:0;;173851:51;;173884:18;;-1:-1:-1;;;173884:18:0;;;;;;;;;;;76879:130;76964:37;76973:5;76980:7;76989:5;76996:4;76964:8;:37::i;157646:174::-;157717:16;157791:21;157754:33;157791:21;157754:9;:33;:::i;:::-;157753:59;;;;:::i;36728:125::-;36788:7;36823:21;35306:2;36788:7;36823:4;;:21;:::i;:::-;36815:30;;;:::i;37038:154::-;37100:6;37140:42;35362:2;35306;37140:4;;:42;:::i;:::-;37133:50;;;:::i;:::-;37126:58;;;37038:154;-1:-1:-1;;;37038:154:0:o;158051:141::-;158115:16;158151:33;158163:21;-1:-1:-1;;;;;158151:33:0;;;:::i;164857:472::-;164995:24;-1:-1:-1;;;;;165036:19:0;;165032:46;;165071:6;165057:21;;165032:46;165176:21;165182:3;165187:9;165176:5;:21::i;:::-;-1:-1:-1;165312:9:0;;164857:472;-1:-1:-1;;164857:472:0:o;37359:132::-;37423:12;37455:28;:4;35362:2;37455:4;;:28;:::i;:::-;37448:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;37448:35:0;;37359:132;-1:-1:-1;;;;;;37359:132:0:o;32690:291::-;32879:17;32933:6;32941:7;32950:9;32961:11;32916:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;32909:64;;32690:291;;;;;;:::o;78667:486::-;78767:24;78794:25;78804:5;78811:7;78794:9;:25::i;:::-;78767:52;;-1:-1:-1;;78834:16:0;:36;78830:316;;;78910:5;78891:16;:24;78887:132;;;78943:60;;-1:-1:-1;;;78943:60:0;;-1:-1:-1;;;;;40474:32:1;;78943:60:0;;;40456:51:1;40523:18;;;40516:34;;;40566:18;;;40559:34;;;40429:18;;78943:60:0;40254:345:1;78887:132:0;79062:57;79071:5;79078:7;79106:5;79087:16;:24;79113:5;79062:8;:57::i;:::-;78756:397;78667:486;;;:::o;73390:308::-;-1:-1:-1;;;;;73474:18:0;;73470:88;;73516:30;;-1:-1:-1;;;73516:30:0;;73543:1;73516:30;;;3618:51:1;3591:18;;73516:30:0;3472:203:1;73470:88:0;-1:-1:-1;;;;;73572:16:0;;73568:88;;73612:32;;-1:-1:-1;;;73612:32:0;;73641:1;73612:32;;;3618:51:1;3591:18;;73612:32:0;3472:203:1;73568:88:0;73666:24;73674:4;73680:2;73684:5;73666:7;:24::i;158423:149::-;158488:15;158530:33;158542:21;158530:9;:33;:::i;35727:516::-;35925:18;;35865:17;;35925:22;;;36070:165;;36212:7;36221:13;36195:40;;;;;;;;40759:19:1;;;40834:3;40812:16;-1:-1:-1;;;;;;40808:51:1;40803:2;40794:12;;40787:73;40885:2;40876:12;;40604:290;36195:40:0;;;;;;;;;;;;;36070:165;;;36113:7;36122:13;36154:10;36167:11;36096:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;36070:165;36063:172;;35727:516;;;;;;:::o;74022:1199::-;-1:-1:-1;;;;;;;;;;;;;;;;74166:18:0;;74162:558;;74322:5;74304:1;:14;;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;74162:558:0;;-1:-1:-1;74162:558:0;;-1:-1:-1;;;;;74382:17:0;;74360:19;74382:17;;;;;;;;;;;74418:19;;;74414:117;;;74465:50;;-1:-1:-1;;;74465:50:0;;-1:-1:-1;;;;;40474:32:1;;74465:50:0;;;40456:51:1;40523:18;;;40516:34;;;40566:18;;;40559:34;;;40429:18;;74465:50:0;40254:345:1;74414:117:0;-1:-1:-1;;;;;74654:17:0;;:11;:17;;;;;;;;;;74674:19;;;;74654:39;;74162:558;-1:-1:-1;;;;;74736:16:0;;74732:439;;74902:14;;;:23;;;;;;;74732:439;;;-1:-1:-1;;;;;75120:15:0;;:11;:15;;;;;;;;;;:24;;;;;;74732:439;75203:2;-1:-1:-1;;;;;75188:25:0;75197:4;-1:-1:-1;;;;;75188:25:0;;75207:5;75188:25;;;;6230::1;;6218:2;6203:18;;6084:177;75188:25:0;;;;;;;;74097:1124;74022:1199;;;:::o;54612:253::-;52070:22;54763:8;;-1:-1:-1;;;;;;54782:19:0;;-1:-1:-1;;;;;54782:19:0;;;;;;;;54817:40;;54763:8;;;;;54817:40;;54686:24;;54817:40;54675:190;;54612:253;:::o;29767:145::-;29835:17;:15;:17::i;:::-;29830:75;;29876:17;;-1:-1:-1;;;29876:17:0;;;;;;;;;;;68936:149;29607:20;:18;:20::i;:::-;69039:38:::1;69062:5;69069:7;69039:22;:38::i;144855:187::-:0;29607:20;:18;:20::i;:::-;144935:22:::1;144947:9;144935:11;:22::i;:::-;144968:30;:28;:30::i;:::-;145009:25;:23;:25::i;138006:194::-:0;138072:17;138119:10;138106:9;:23;138102:62;;138138:26;;-1:-1:-1;;;138138:26:0;;138154:9;138138:26;;;6230:25:1;6203:18;;138138:26:0;6084:177:1;138102:62:0;-1:-1:-1;138182:10:0;138006:194::o;138586:417::-;138741:15;138759:8;-1:-1:-1;;;;;138759:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;138741:36;-1:-1:-1;;;;;;138792:21:0;;138788:54;;138822:20;;-1:-1:-1;;;138822:20:0;;;;;;;;;;;138788:54;138919:76;-1:-1:-1;;;;;138919:32:0;;138952:10;138972:8;138983:11;138919:32;:76::i;77876:499::-;-1:-1:-1;;;;;;;;;;;;;;;;78043:19:0;;78039:91;;78086:32;;-1:-1:-1;;;78086:32:0;;78115:1;78086:32;;;3618:51:1;3591:18;;78086:32:0;3472:203:1;78039:91:0;-1:-1:-1;;;;;78144:21:0;;78140:92;;78189:31;;-1:-1:-1;;;78189:31:0;;78217:1;78189:31;;;3618:51:1;3591:18;;78189:31:0;3472:203:1;78140:92:0;-1:-1:-1;;;;;78242:20:0;;;;;;;:13;;;:20;;;;;;;;:29;;;;;;;;;:37;;;78290:78;;;;78341:7;-1:-1:-1;;;;;78325:31:0;78334:5;-1:-1:-1;;;;;78325:31:0;;78350:5;78325:31;;;;6230:25:1;;6218:2;6203:18;;6084:177;78325:31:0;;;;;;;;77974:401;77876:499;;;;:::o;31207:122::-;31257:4;31281:26;:24;:26::i;:::-;:40;-1:-1:-1;;;31281:40:0;;;;;;-1:-1:-1;31207:122:0:o;69093:220::-;29607:20;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;69260:7:0;:15:::1;69270:5:::0;69260:7;:15:::1;:::i;:::-;-1:-1:-1::0;69286:9:0::1;::::0;::::1;:19;69298:7:::0;69286:9;:19:::1;:::i;140263:193::-:0;29607:20;:18;:20::i;:::-;140340:26:::1;140356:9;140340:15;:26::i;127702:68::-:0;29607:20;:18;:20::i;83038:190::-;83166:53;;;-1:-1:-1;;;;;41807:32:1;;;83166:53:0;;;41789:51:1;41876:32;;41856:18;;;41849:60;41925:18;;;;41918:34;;;83166:53:0;;;;;;;;;;41762:18:1;;;;83166:53:0;;;;;;;;-1:-1:-1;;;;;83166:53:0;-1:-1:-1;;;83166:53:0;;;83139:81;;83159:5;;83139:19;:81::i;98433:125::-;29607:20;:18;:20::i;:::-;98514:36:::1;98540:9;98514:25;:36::i;89922:738::-:0;90003:18;90032:19;90172:4;90169:1;90162:4;90156:11;90149:4;90143;90139:15;90136:1;90129:5;90122;90117:60;90231:7;90221:180;;90276:4;90270:11;90322:16;90319:1;90314:3;90299:40;90369:16;90364:3;90357:29;90221:180;-1:-1:-1;;90480:1:0;90474:8;90429:16;;-1:-1:-1;90509:15:0;;:68;;90561:11;90576:1;90561:16;;90509:68;;;-1:-1:-1;;;;;90527:26:0;;;:31;90509:68;90505:148;;;90601:40;;-1:-1:-1;;;90601:40:0;;-1:-1:-1;;;;;3636:32:1;;90601:40:0;;;3618:51:1;3591:18;;90601:40:0;3472:203:1;98566:194:0;29607:20;:18;:20::i;:::-;-1:-1:-1;;;;;98661:23:0;::::1;98657:53;;98693:17;;-1:-1:-1::0;;;98693:17:0::1;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:131:1:-;-1:-1:-1;;;;;89:31:1;;79:42;;69:70;;135:1;132;125:12;150:247;209:6;262:2;250:9;241:7;237:23;233:32;230:52;;;278:1;275;268:12;230:52;317:9;304:23;336:31;361:5;336:31;:::i;594:289::-;636:3;674:5;668:12;701:6;696:3;689:19;757:6;750:4;743:5;739:16;732:4;727:3;723:14;717:47;809:1;802:4;793:6;788:3;784:16;780:27;773:38;872:4;865:2;861:7;856:2;848:6;844:15;840:29;835:3;831:39;827:50;820:57;;;594:289;;;;:::o;888:220::-;1037:2;1026:9;1019:21;1000:4;1057:45;1098:2;1087:9;1083:18;1075:6;1057:45;:::i;1113:367::-;1181:6;1189;1242:2;1230:9;1221:7;1217:23;1213:32;1210:52;;;1258:1;1255;1248:12;1210:52;1297:9;1284:23;1316:31;1341:5;1316:31;:::i;:::-;1366:5;1444:2;1429:18;;;;1416:32;;-1:-1:-1;;;1113:367:1:o;1485:158::-;1547:5;1592:3;1583:6;1578:3;1574:16;1570:26;1567:46;;;1609:1;1606;1599:12;1567:46;-1:-1:-1;1631:6:1;1485:158;-1:-1:-1;1485:158:1:o;1648:360::-;1736:6;1789:2;1777:9;1768:7;1764:23;1760:32;1757:52;;;1805:1;1802;1795:12;1757:52;1845:9;1832:23;-1:-1:-1;;;;;1870:6:1;1867:30;1864:50;;;1910:1;1907;1900:12;1864:50;1933:69;1994:7;1985:6;1974:9;1970:22;1933:69;:::i;2167:1300::-;2087:12;;2075:25;;2149:4;2138:16;;;2132:23;2116:14;;;2109:47;2533:4;2581:3;2566:19;;2675:3;2670:2;2659:9;2655:18;2648:31;2699:6;2734;2728:13;2765:6;2757;2750:22;2803:3;2792:9;2788:19;2781:26;;2866:3;2856:6;2853:1;2849:14;2838:9;2834:30;2830:40;2816:54;;2905:4;2897:6;2893:17;2928:1;2938:437;2952:6;2949:1;2946:13;2938:437;;;3045:3;3041:8;3029:9;3021:6;3017:22;3013:37;3008:3;3001:50;3080:6;3074:13;3121:2;3115:9;3107:6;3100:25;3172:4;3168:2;3164:13;3158:20;3138:40;;3217:2;3210:4;3202:6;3198:17;3191:29;3243:48;3287:2;3279:6;3275:15;3261:12;3243:48;:::i;:::-;3233:58;-1:-1:-1;;3326:4:1;3351:14;;;;3314:17;;;;;2974:1;2967:9;2938:437;;;-1:-1:-1;;2087:12:1;;3457:2;3442:18;;2075:25;-1:-1:-1;;2149:4:1;2138:16;;2132:23;2116:14;;;2109:47;3392:6;-1:-1:-1;3407:54:1;2013:149;3680:154;3739:5;3784:2;3775:6;3770:3;3766:16;3762:25;3759:45;;;3800:1;3797;3790:12;3839:347;3890:8;3900:6;3954:3;3947:4;3939:6;3935:17;3931:27;3921:55;;3972:1;3969;3962:12;3921:55;-1:-1:-1;3995:20:1;;-1:-1:-1;;;;;4027:30:1;;4024:50;;;4070:1;4067;4060:12;4024:50;4107:4;4099:6;4095:17;4083:29;;4159:3;4152:4;4143:6;4135;4131:19;4127:30;4124:39;4121:59;;;4176:1;4173;4166:12;4121:59;3839:347;;;;;:::o;4191:1095::-;4334:6;4342;4350;4358;4366;4374;4382;4435:3;4423:9;4414:7;4410:23;4406:33;4403:53;;;4452:1;4449;4442:12;4403:53;4475;4520:7;4509:9;4475:53;:::i;:::-;4465:63;-1:-1:-1;4597:2:1;4582:18;;4569:32;;-1:-1:-1;4676:3:1;4661:19;;4648:33;-1:-1:-1;;;;;4693:30:1;;4690:50;;;4736:1;4733;4726:12;4690:50;4775:58;4825:7;4816:6;4805:9;4801:22;4775:58;:::i;:::-;4852:8;;-1:-1:-1;4749:84:1;-1:-1:-1;;4939:3:1;4924:19;;4911:33;4953;4911;4953;:::i;:::-;5005:7;-1:-1:-1;5065:3:1;5050:19;;5037:33;-1:-1:-1;;;;;5082:32:1;;5079:52;;;5127:1;5124;5117:12;5079:52;5166:60;5218:7;5207:8;5196:9;5192:24;5166:60;:::i;:::-;4191:1095;;;;-1:-1:-1;4191:1095:1;;-1:-1:-1;4191:1095:1;;;;5140:86;;-1:-1:-1;;;4191:1095:1:o;6266:508::-;6343:6;6351;6359;6412:2;6400:9;6391:7;6387:23;6383:32;6380:52;;;6428:1;6425;6418:12;6380:52;6467:9;6454:23;6486:31;6511:5;6486:31;:::i;:::-;6536:5;-1:-1:-1;6593:2:1;6578:18;;6565:32;6606:33;6565:32;6606:33;:::i;:::-;6266:508;;6658:7;;-1:-1:-1;;;6738:2:1;6723:18;;;;6710:32;;6266:508::o;6779:367::-;6842:8;6852:6;6906:3;6899:4;6891:6;6887:17;6883:27;6873:55;;6924:1;6921;6914:12;6873:55;-1:-1:-1;6947:20:1;;-1:-1:-1;;;;;6979:30:1;;6976:50;;;7022:1;7019;7012:12;6976:50;7059:4;7051:6;7047:17;7035:29;;7119:3;7112:4;7102:6;7099:1;7095:14;7087:6;7083:27;7079:38;7076:47;7073:67;;;7136:1;7133;7126:12;7151:768;7273:6;7281;7289;7297;7350:2;7338:9;7329:7;7325:23;7321:32;7318:52;;;7366:1;7363;7356:12;7318:52;7406:9;7393:23;-1:-1:-1;;;;;7431:6:1;7428:30;7425:50;;;7471:1;7468;7461:12;7425:50;7510:70;7572:7;7563:6;7552:9;7548:22;7510:70;:::i;:::-;7599:8;;-1:-1:-1;7484:96:1;-1:-1:-1;;7687:2:1;7672:18;;7659:32;-1:-1:-1;;;;;7703:32:1;;7700:52;;;7748:1;7745;7738:12;7700:52;7787:72;7851:7;7840:8;7829:9;7825:24;7787:72;:::i;:::-;7151:768;;;;-1:-1:-1;7878:8:1;-1:-1:-1;;;;7151:768:1:o;8295:163::-;8362:20;;8422:10;8411:22;;8401:33;;8391:61;;8448:1;8445;8438:12;8391:61;8295:163;;;:::o;8463:298::-;8530:6;8538;8591:2;8579:9;8570:7;8566:23;8562:32;8559:52;;;8607:1;8604;8597:12;8559:52;8630:28;8648:9;8630:28;:::i;8766:118::-;8852:5;8845:13;8838:21;8831:5;8828:32;8818:60;;8874:1;8871;8864:12;8889:489;8983:6;8991;9044:2;9032:9;9023:7;9019:23;9015:32;9012:52;;;9060:1;9057;9050:12;9012:52;9100:9;9087:23;-1:-1:-1;;;;;9125:6:1;9122:30;9119:50;;;9165:1;9162;9155:12;9119:50;9188:69;9249:7;9240:6;9229:9;9225:22;9188:69;:::i;:::-;9178:79;;;9307:2;9296:9;9292:18;9279:32;9320:28;9342:5;9320:28;:::i;:::-;9367:5;9357:15;;;8889:489;;;;;:::o;9383:257::-;2087:12;;2075:25;;2149:4;2138:16;;;2132:23;2116:14;;;2109:47;9577:2;9562:18;;9589:45;2013:149;9645:156;9711:20;;9771:4;9760:16;;9750:27;;9740:55;;9791:1;9788;9781:12;9806:127;9867:10;9862:3;9858:20;9855:1;9848:31;9898:4;9895:1;9888:15;9922:4;9919:1;9912:15;9938:251;10010:2;10004:9;;;10040:15;;-1:-1:-1;;;;;10070:34:1;;10106:22;;;10067:62;10064:88;;;10132:18;;:::i;:::-;10168:2;10161:22;9938:251;:::o;10194:275::-;10265:2;10259:9;10330:2;10311:13;;-1:-1:-1;;10307:27:1;10295:40;;-1:-1:-1;;;;;10350:34:1;;10386:22;;;10347:62;10344:88;;;10412:18;;:::i;:::-;10448:2;10441:22;10194:275;;-1:-1:-1;10194:275:1:o;10474:187::-;10523:4;-1:-1:-1;;;;;10548:6:1;10545:30;10542:56;;;10578:18;;:::i;:::-;-1:-1:-1;10644:2:1;10623:15;-1:-1:-1;;10619:29:1;10650:4;10615:40;;10474:187::o;10666:488::-;10709:5;10762:3;10755:4;10747:6;10743:17;10739:27;10729:55;;10780:1;10777;10770:12;10729:55;10820:6;10807:20;10851:53;10867:36;10896:6;10867:36;:::i;:::-;10851:53;:::i;:::-;10929:6;10920:7;10913:23;10983:3;10976:4;10967:6;10959;10955:19;10951:30;10948:39;10945:59;;;11000:1;10997;10990:12;10945:59;11065:6;11058:4;11050:6;11046:17;11039:4;11030:7;11026:18;11013:59;11121:1;11092:20;;;11114:4;11088:31;11081:42;;;;11096:7;10666:488;-1:-1:-1;;;10666:488:1:o;11159:744::-;11263:6;11271;11279;11287;11340:3;11328:9;11319:7;11315:23;11311:33;11308:53;;;11357:1;11354;11347:12;11308:53;11396:9;11383:23;11415:31;11440:5;11415:31;:::i;:::-;11465:5;-1:-1:-1;11489:36:1;11521:2;11506:18;;11489:36;:::i;:::-;11479:46;;11576:2;11565:9;11561:18;11548:32;-1:-1:-1;;;;;11595:6:1;11592:30;11589:50;;;11635:1;11632;11625:12;11589:50;11658;11700:7;11691:6;11680:9;11676:22;11658:50;:::i;:::-;11648:60;;;11761:2;11750:9;11746:18;11733:32;-1:-1:-1;;;;;11780:8:1;11777:32;11774:52;;;11822:1;11819;11812:12;11774:52;11845;11889:7;11878:8;11867:9;11863:24;11845:52;:::i;:::-;11835:62;;;11159:744;;;;;;;:::o;11908:159::-;11975:20;;12035:6;12024:18;;12014:29;;12004:57;;12057:1;12054;12047:12;12072:256;12138:6;12146;12199:2;12187:9;12178:7;12174:23;12170:32;12167:52;;;12215:1;12212;12205:12;12167:52;12238:28;12256:9;12238:28;:::i;:::-;12228:38;;12285:37;12318:2;12307:9;12303:18;12285:37;:::i;:::-;12275:47;;12072:256;;;;;:::o;12998:670::-;13112:6;13120;13128;13136;13189:3;13177:9;13168:7;13164:23;13160:33;13157:53;;;13206:1;13203;13196:12;13157:53;13229;13274:7;13263:9;13229:53;:::i;:::-;13219:63;;13333:2;13322:9;13318:18;13305:32;-1:-1:-1;;;;;13352:6:1;13349:30;13346:50;;;13392:1;13389;13382:12;13346:50;13431:58;13481:7;13472:6;13461:9;13457:22;13431:58;:::i;:::-;13508:8;;-1:-1:-1;13405:84:1;-1:-1:-1;;13593:3:1;13578:19;;13565:33;13607:31;13565:33;13607:31;:::i;:::-;12998:670;;;;-1:-1:-1;12998:670:1;;-1:-1:-1;;12998:670:1:o;13673:1238::-;14079:3;14074;14070:13;14062:6;14058:26;14047:9;14040:45;14121:3;14116:2;14105:9;14101:18;14094:31;14021:4;14148:46;14189:3;14178:9;14174:19;14166:6;14148:46;:::i;:::-;14242:9;14234:6;14230:22;14225:2;14214:9;14210:18;14203:50;14276:33;14302:6;14294;14276:33;:::i;:::-;14340:2;14325:18;;14318:34;;;-1:-1:-1;;;;;14389:32:1;;14383:3;14368:19;;14361:61;14409:3;14438:19;;14431:35;;;14503:22;;;14497:3;14482:19;;14475:51;14575:13;;14597:22;;;14647:2;14673:15;;;;-1:-1:-1;14635:15:1;;;;-1:-1:-1;14716:169:1;14730:6;14727:1;14724:13;14716:169;;;14791:13;;14779:26;;14834:2;14860:15;;;;14825:12;;;;14752:1;14745:9;14716:169;;;-1:-1:-1;14902:3:1;;13673:1238;-1:-1:-1;;;;;;;;;;;13673:1238:1:o;14916:475::-;15040:6;15048;15101:2;15089:9;15080:7;15076:23;15072:32;15069:52;;;15117:1;15114;15107:12;15069:52;15157:9;15144:23;-1:-1:-1;;;;;15182:6:1;15179:30;15176:50;;;15222:1;15219;15212:12;15176:50;15261:70;15323:7;15314:6;15303:9;15299:22;15261:70;:::i;:::-;15350:8;;15235:96;;-1:-1:-1;14916:475:1;-1:-1:-1;;;;14916:475:1:o;15396:184::-;15454:6;15507:2;15495:9;15486:7;15482:23;15478:32;15475:52;;;15523:1;15520;15513:12;15475:52;15546:28;15564:9;15546:28;:::i;15585:553::-;15671:6;15679;15687;15695;15748:2;15736:9;15727:7;15723:23;15719:32;15716:52;;;15764:1;15761;15754:12;15716:52;15787:28;15805:9;15787:28;:::i;:::-;15777:38;;15834:37;15867:2;15856:9;15852:18;15834:37;:::i;:::-;15824:47;;15922:2;15911:9;15907:18;15894:32;-1:-1:-1;;;;;15941:6:1;15938:30;15935:50;;;15981:1;15978;15971:12;15935:50;16020:58;16070:7;16061:6;16050:9;16046:22;16020:58;:::i;16618:657::-;16756:6;16764;16772;16816:9;16807:7;16803:23;16846:3;16842:2;16838:12;16835:32;;;16863:1;16860;16853:12;16835:32;16903:9;16890:23;-1:-1:-1;;;;;16928:6:1;16925:30;16922:50;;;16968:1;16965;16958:12;16922:50;16991:69;17052:7;17043:6;17032:9;17028:22;16991:69;:::i;:::-;16981:79;-1:-1:-1;;17094:2:1;-1:-1:-1;;17076:16:1;;17072:25;17069:45;;;17110:1;17107;17100:12;17069:45;;17148:2;17137:9;17133:18;17123:28;;17201:2;17190:9;17186:18;17173:32;17214:31;17239:5;17214:31;:::i;:::-;17264:5;17254:15;;;16618:657;;;;;:::o;17280:613::-;17524:4;17566:3;17555:9;17551:19;17543:27;;17603:6;17597:13;17586:9;17579:32;-1:-1:-1;;;;;17671:4:1;17663:6;17659:17;17653:24;17649:49;17642:4;17631:9;17627:20;17620:79;17746:4;17738:6;17734:17;17728:24;17761:62;17817:4;17806:9;17802:20;17788:12;2087;;2075:25;;2149:4;2138:16;;;2132:23;2116:14;;2109:47;2013:149;17761:62;-1:-1:-1;2087:12:1;;17882:3;17867:19;;2075:25;2149:4;2138:16;;2132:23;2116:14;;;2109:47;17832:55;2013:149;17898:942;18009:6;18017;18025;18033;18041;18049;18057;18110:3;18098:9;18089:7;18085:23;18081:33;18078:53;;;18127:1;18124;18117:12;18078:53;18166:9;18153:23;18185:31;18210:5;18185:31;:::i;:::-;18235:5;-1:-1:-1;18292:2:1;18277:18;;18264:32;18305:33;18264:32;18305:33;:::i;:::-;18357:7;-1:-1:-1;18437:2:1;18422:18;;18409:32;;-1:-1:-1;18540:2:1;18525:18;;18512:32;;-1:-1:-1;18589:37:1;18621:3;18606:19;;18589:37;:::i;:::-;17898:942;;;;-1:-1:-1;17898:942:1;;;;18579:47;18699:3;18684:19;;18671:33;;-1:-1:-1;18803:3:1;18788:19;;;18775:33;;17898:942;-1:-1:-1;;17898:942:1:o;18845:388::-;18913:6;18921;18974:2;18962:9;18953:7;18949:23;18945:32;18942:52;;;18990:1;18987;18980:12;18942:52;19029:9;19016:23;19048:31;19073:5;19048:31;:::i;:::-;19098:5;-1:-1:-1;19155:2:1;19140:18;;19127:32;19168:33;19127:32;19168:33;:::i;19238:236::-;19323:6;19376:2;19364:9;19355:7;19351:23;19347:32;19344:52;;;19392:1;19389;19382:12;19344:52;19415:53;19460:7;19449:9;19415:53;:::i;19479:380::-;19558:1;19554:12;;;;19601;;;19622:61;;19676:4;19668:6;19664:17;19654:27;;19622:61;19729:2;19721:6;19718:14;19698:18;19695:38;19692:161;;19775:10;19770:3;19766:20;19763:1;19756:31;19810:4;19807:1;19800:15;19838:4;19835:1;19828:15;20132:127;20193:10;20188:3;20184:20;20181:1;20174:31;20224:4;20221:1;20214:15;20248:4;20245:1;20238:15;20390:518;20492:2;20487:3;20484:11;20481:421;;;20528:5;20525:1;20518:16;20572:4;20569:1;20559:18;20642:2;20630:10;20626:19;20623:1;20619:27;20613:4;20609:38;20678:4;20666:10;20663:20;20660:47;;;-1:-1:-1;20701:4:1;20660:47;20756:2;20751:3;20747:12;20744:1;20740:20;20734:4;20730:31;20720:41;;20811:81;20829:2;20822:5;20819:13;20811:81;;;20888:1;20874:16;;20855:1;20844:13;20811:81;;21084:1299;21210:3;21204:10;-1:-1:-1;;;;;21229:6:1;21226:30;21223:56;;;21259:18;;:::i;:::-;21288:97;21378:6;21338:38;21370:4;21364:11;21338:38;:::i;:::-;21332:4;21288:97;:::i;:::-;21434:4;21465:2;21454:14;;21482:1;21477:649;;;;22170:1;22187:6;22184:89;;;-1:-1:-1;22239:19:1;;;22233:26;22184:89;-1:-1:-1;;21041:1:1;21037:11;;;21033:24;21029:29;21019:40;21065:1;21061:11;;;21016:57;22286:81;;21447:930;;21477:649;20337:1;20330:14;;;20374:4;20361:18;;-1:-1:-1;;21513:20:1;;;21631:222;21645:7;21642:1;21639:14;21631:222;;;21727:19;;;21721:26;21706:42;;21834:4;21819:20;;;;21787:1;21775:14;;;;21661:12;21631:222;;;21635:3;21881:6;21872:7;21869:19;21866:201;;;21942:19;;;21936:26;-1:-1:-1;;22025:1:1;22021:14;;;22037:3;22017:24;22013:37;22009:42;21994:58;21979:74;;21866:201;-1:-1:-1;;;;22113:1:1;22097:14;;;22093:22;22080:36;;-1:-1:-1;21084:1299:1:o;22388:799::-;22518:3;22547:1;22580:6;22574:13;22610:36;22636:9;22610:36;:::i;:::-;22677:1;22662:17;;22688:133;;;;22835:1;22830:332;;;;22655:507;;22688:133;-1:-1:-1;;22721:24:1;;22709:37;;22794:14;;22787:22;22775:35;;22766:45;;;-1:-1:-1;22688:133:1;;22830:332;22861:6;22858:1;22851:17;22909:4;22906:1;22896:18;22936:1;22950:166;22964:6;22961:1;22958:13;22950:166;;;23044:14;;23031:11;;;23024:35;23100:1;23087:15;;;;22986:4;22979:12;22950:166;;;22954:3;;23145:6;23140:3;23136:16;23129:23;;22655:507;-1:-1:-1;23178:3:1;;22388:799;-1:-1:-1;;;;;22388:799:1:o;23900:127::-;23961:10;23956:3;23952:20;23949:1;23942:31;23992:4;23989:1;23982:15;24016:4;24013:1;24006:15;24032:125;24097:9;;;24118:10;;;24115:36;;;24131:18;;:::i;24441:335::-;24545:4;24603:11;24590:25;24697:2;24693:7;24682:8;24666:14;24662:29;24658:43;24638:18;24634:68;24624:96;;24716:1;24713;24706:12;24624:96;24737:33;;;;;24441:335;-1:-1:-1;;24441:335:1:o;24781:521::-;24858:4;24864:6;24924:11;24911:25;25018:2;25014:7;25003:8;24987:14;24983:29;24979:43;24959:18;24955:68;24945:96;;25037:1;25034;25027:12;24945:96;25064:33;;25116:20;;;-1:-1:-1;;;;;;25148:30:1;;25145:50;;;25191:1;25188;25181:12;25145:50;25224:4;25212:17;;-1:-1:-1;25255:14:1;25251:27;;;25241:38;;25238:58;;;25292:1;25289;25282:12;25307:184;25365:6;25418:2;25406:9;25397:7;25393:23;25389:32;25386:52;;;25434:1;25431;25424:12;25386:52;25457:28;25475:9;25457:28;:::i;25496:1196::-;-1:-1:-1;;;;;25613:3:1;25610:27;25607:53;;;25640:18;;:::i;:::-;25669:94;25759:3;25719:38;25751:4;25745:11;25719:38;:::i;:::-;25713:4;25669:94;:::i;:::-;25789:1;25814:2;25809:3;25806:11;25831:1;25826:608;;;;26478:1;26495:3;26492:93;;;-1:-1:-1;26551:19:1;;;26538:33;26492:93;-1:-1:-1;;21041:1:1;21037:11;;;21033:24;21029:29;21019:40;21065:1;21061:11;;;21016:57;26598:78;;25799:887;;25826:608;20337:1;20330:14;;;20374:4;20361:18;;-1:-1:-1;;25862:17:1;;;25977:229;25991:7;25988:1;25985:14;25977:229;;;26080:19;;;26067:33;26052:49;;26187:4;26172:20;;;;26140:1;26128:14;;;;26007:12;25977:229;;;25981:3;26234;26225:7;26222:16;26219:159;;;26358:1;26354:6;26348:3;26342;26339:1;26335:11;26331:21;26327:34;26323:39;26310:9;26305:3;26301:19;26288:33;26284:79;26276:6;26269:95;26219:159;;;26421:1;26415:3;26412:1;26408:11;26404:19;26398:4;26391:33;25799:887;;25496:1196;;;:::o;26697:266::-;26785:6;26780:3;26773:19;26837:6;26830:5;26823:4;26818:3;26814:14;26801:43;-1:-1:-1;26889:1:1;26864:16;;;26882:4;26860:27;;;26853:38;;;;26945:2;26924:15;;;-1:-1:-1;;26920:29:1;26911:39;;;26907:50;;26697:266::o;26968:1728::-;27242:2;27254:21;;;27227:18;;27310:22;;;-1:-1:-1;27363:2:1;27412:1;27408:14;;;27393:30;;27389:39;;;27348:18;;27451:6;-1:-1:-1;;;27503:14:1;27499:27;;;27495:41;27545:1122;27559:6;27556:1;27553:13;27545:1122;;;27624:22;;;-1:-1:-1;;27620:36:1;27608:49;;27696:20;;27739:27;;;27729:55;;27780:1;27777;27770:12;27729:55;27810:31;;27899:10;27873:24;27810:31;27873:24;:::i;:::-;27869:41;27861:6;27854:57;27987:6;27952:33;27981:2;27974:5;27970:14;27952:33;:::i;:::-;27948:46;27943:2;27935:6;27931:15;27924:71;28060:2;28053:5;28049:14;28036:28;28149:2;28145:7;28137:5;28121:14;28117:26;28113:40;28091:20;28087:67;28077:95;;28168:1;28165;28158:12;28077:95;28200:32;28321:2;28308:16;;;28259:21;-1:-1:-1;;;;;28340:30:1;;28337:50;;;28383:1;28380;28373:12;28337:50;28436:6;28420:14;28416:27;28407:7;28403:41;28400:61;;;28457:1;28454;28447:12;28400:61;28498:4;28493:2;28485:6;28481:15;28474:29;28526:61;28581:4;28573:6;28569:17;28561:6;28552:7;28526:61;:::i;:::-;28516:71;;;;28622:2;28614:6;28610:15;28600:25;;28654:2;28649:3;28645:12;28638:19;;27581:1;27578;27574:9;27569:14;;27545:1122;;;-1:-1:-1;28684:6:1;;26968:1728;-1:-1:-1;;;;;;;26968:1728:1:o;28701:331::-;28806:9;28817;28859:8;28847:10;28844:24;28841:44;;;28881:1;28878;28871:12;28841:44;28910:6;28900:8;28897:20;28894:40;;;28930:1;28927;28920:12;28894:40;-1:-1:-1;;28956:23:1;;;29001:25;;;;;-1:-1:-1;28701:331:1:o;29037:211::-;29078:3;29116:5;29110:12;29160:6;29153:4;29146:5;29142:16;29137:3;29131:36;29222:1;29186:16;;29211:13;;;-1:-1:-1;29186:16:1;;29037:211;-1:-1:-1;29037:211:1:o;29253:369::-;29444:3;29472:29;29497:3;29489:6;29472:29;:::i;:::-;29535:6;29527;29523:2;29510:32;29596:1;29561:15;;29585:13;;;-1:-1:-1;29561:15:1;;29253:369;-1:-1:-1;;;29253:369:1:o;29627:244::-;29784:2;29773:9;29766:21;29747:4;29804:61;29861:2;29850:9;29846:18;29838:6;29830;29804:61;:::i;29876:331::-;29975:4;30033:11;30020:25;30127:3;30123:8;30112;30096:14;30092:29;30088:44;30068:18;30064:69;30054:97;;30147:1;30144;30137:12;30212:129;-1:-1:-1;;;;;30290:5:1;30286:30;30279:5;30276:41;30266:69;;30331:1;30328;30321:12;30346:1044;30724:10;30697:25;30715:6;30697:25;:::i;:::-;30693:42;30675:61;;30802:4;30790:17;;;30777:31;30824:20;;;30817:35;30656:4;30901;30889:17;;30876:31;30916:32;30876:31;30916:32;:::i;:::-;-1:-1:-1;;;;;30990:7:1;30986:32;30979:4;30968:9;30964:20;30957:62;;31055:6;31050:2;31039:9;31035:18;31028:34;31099:3;31093;31082:9;31078:19;31071:32;31126:62;31183:3;31172:9;31168:19;31160:6;31152;31126:62;:::i;:::-;-1:-1:-1;;;;;31225:32:1;;31245:3;31204:19;;31197:61;31295:22;;;31289:3;31274:19;;31267:51;31335:49;31299:6;31369;31361;31335:49;:::i;:::-;31327:57;30346:1044;-1:-1:-1;;;;;;;;;;30346:1044:1:o;31395:686::-;31474:6;31527:2;31515:9;31506:7;31502:23;31498:32;31495:52;;;31543:1;31540;31533:12;31495:52;31576:9;31570:16;-1:-1:-1;;;;;31601:6:1;31598:30;31595:50;;;31641:1;31638;31631:12;31595:50;31664:22;;31717:4;31709:13;;31705:27;-1:-1:-1;31695:55:1;;31746:1;31743;31736:12;31695:55;31779:2;31773:9;31804:53;31820:36;31849:6;31820:36;:::i;31804:53::-;31880:6;31873:5;31866:21;31928:7;31923:2;31914:6;31910:2;31906:15;31902:24;31899:37;31896:57;;;31949:1;31946;31939:12;31896:57;31997:6;31992:2;31988;31984:11;31979:2;31972:5;31968:14;31962:42;32049:1;32024:18;;;32044:2;32020:27;32013:38;;;;32028:5;31395:686;-1:-1:-1;;;;31395:686:1:o;32086:489::-;32175:6;32235:2;32223:9;32214:7;32210:23;32206:32;32250:2;32247:22;;;32265:1;32262;32255:12;32247:22;-1:-1:-1;32307:22:1;;:::i;:::-;32374:23;;32406:22;;32501:2;32486:18;;;32473:32;32521:14;;;32514:31;;;;-1:-1:-1;32413:5:1;32086:489;-1:-1:-1;32086:489:1:o;33511:135::-;33550:3;33571:17;;;33568:43;;33591:18;;:::i;:::-;-1:-1:-1;33638:1:1;33627:13;;33511:135::o;34101:245::-;34159:6;34212:2;34200:9;34191:7;34187:23;34183:32;34180:52;;;34228:1;34225;34218:12;34180:52;34267:9;34254:23;34286:30;34310:5;34286:30;:::i;34351:479::-;34618:1;34614;34609:3;34605:11;34601:19;34593:6;34589:32;34578:9;34571:51;34658:6;34653:2;34642:9;34638:18;34631:34;34713:6;34705;34701:19;34696:2;34685:9;34681:18;34674:47;34757:3;34752:2;34741:9;34737:18;34730:31;34552:4;34778:46;34819:3;34808:9;34804:19;34796:6;34778:46;:::i;:::-;34770:54;34351:479;-1:-1:-1;;;;;;34351:479:1:o;35103:379::-;35296:2;35285:9;35278:21;35259:4;35322:45;35363:2;35352:9;35348:18;35340:6;35322:45;:::i;:::-;35415:9;35407:6;35403:22;35398:2;35387:9;35383:18;35376:50;35443:33;35469:6;35461;35443:33;:::i;35487:245::-;35554:6;35607:2;35595:9;35586:7;35582:23;35578:32;35575:52;;;35623:1;35620;35613:12;35575:52;35655:9;35649:16;35674:28;35696:5;35674:28;:::i;35737:891::-;35960:2;35949:9;35942:21;36018:10;36009:6;36003:13;35999:30;35994:2;35983:9;35979:18;35972:58;36084:4;36076:6;36072:17;36066:24;36061:2;36050:9;36046:18;36039:52;35923:4;36138:2;36130:6;36126:15;36120:22;36179:4;36173:3;36162:9;36158:19;36151:33;36207:52;36254:3;36243:9;36239:19;36225:12;36207:52;:::i;:::-;36193:66;;36308:2;36300:6;36296:15;36290:22;36382:2;36378:7;36366:9;36358:6;36354:22;36350:36;36343:4;36332:9;36328:20;36321:66;36410:41;36444:6;36428:14;36410:41;:::i;:::-;36520:3;36508:16;;;;36502:23;36495:31;36488:39;36482:3;36467:19;;36460:68;-1:-1:-1;;;;;;;;36589:32:1;;;;36582:4;36567:20;;;36560:62;36396:55;35737:891::o;36633:388::-;36703:5;36751:4;36739:9;36734:3;36730:19;36726:30;36723:50;;;36769:1;36766;36759:12;36723:50;36791:22;;:::i;:::-;36858:16;;36883:22;;36971:2;36956:18;;;36950:25;36991:14;;;36984:31;;;;-1:-1:-1;36782:31:1;36633:388;-1:-1:-1;36633:388:1:o;37026:259::-;37126:6;37179:2;37167:9;37158:7;37154:23;37150:32;37147:52;;;37195:1;37192;37185:12;37147:52;37218:61;37271:7;37260:9;37218:61;:::i;37290:323::-;37410:19;;-1:-1:-1;;;;;;37447:24:1;;;37491:1;37483:10;;37480:127;;;-1:-1:-1;;;;;;37552:1:1;37548:11;;;;37545:1;37541:19;37537:41;;;37529:50;37525:72;;;;37290:323;-1:-1:-1;;37290:323:1:o;37618:740::-;37722:6;37782:3;37770:9;37761:7;37757:23;37753:33;37798:2;37795:22;;;37813:1;37810;37803:12;37795:22;-1:-1:-1;37882:2:1;37876:9;37924:4;37912:17;;-1:-1:-1;;;;;37944:34:1;;37980:22;;;37941:62;37938:88;;;38006:18;;:::i;:::-;38042:2;38035:22;38081:16;;38066:32;;38141:2;38126:18;;38120:25;38154:30;38120:25;38154:30;:::i;:::-;38212:2;38200:15;;38193:30;38256:70;38318:7;38313:2;38298:18;;38256:70;:::i;:::-;38251:2;38239:15;;38232:95;38243:6;37618:740;-1:-1:-1;;;37618:740:1:o;38766:217::-;38806:1;38832;38822:132;;38876:10;38871:3;38867:20;38864:1;38857:31;38911:4;38908:1;38901:15;38939:4;38936:1;38929:15;38822:132;-1:-1:-1;38968:9:1;;38766:217::o;38988:168::-;39061:9;;;39092;;39109:15;;;39103:22;;39089:37;39079:71;;39130:18;;:::i;39161:255::-;39281:19;;39320:2;39312:11;;39309:101;;;-1:-1:-1;;39381:2:1;39377:12;;;39374:1;39370:20;39366:33;39355:45;39161:255;;;;:::o;39421:362::-;39541:19;;-1:-1:-1;;;;;;39578:37:1;;;39635:1;39627:10;;39624:153;;;-1:-1:-1;;;;;;39696:1:1;39692:11;;;;39689:1;39685:19;39681:54;;;39673:63;39669:98;;;;39421:362;-1:-1:-1;;39421:362:1:o;39788:461::-;40053:3;40031:16;;;-1:-1:-1;;;;;;40027:51:1;40015:64;;40134:3;40112:16;;;-1:-1:-1;;;;;;40108:43:1;40104:1;40095:11;;40088:64;40177:2;40168:12;;40161:28;;;-1:-1:-1;40205:38:1;40239:2;40230:12;;40222:6;40205:38;:::i;40899:427::-;41140:6;41135:3;41128:19;-1:-1:-1;;;;;41203:3:1;41199:28;41190:6;41185:3;41181:16;41177:51;41172:2;41167:3;41163:12;41156:73;41259:6;41254:2;41249:3;41245:12;41238:28;41110:3;41282:38;41316:2;41311:3;41307:12;41299:6;41282:38;:::i;41331:251::-;41401:6;41454:2;41442:9;41433:7;41429:23;41425:32;41422:52;;;41470:1;41467;41460:12;41422:52;41502:9;41496:16;41521:31;41546:5;41521:31;:::i
Swarm Source
ipfs://b28d93f9c39f9e9b08eb020938d3ac2d50af7b10d52d8d6f49e5928cf6700b58
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.