Source Code
Latest 25 from a total of 58 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Bridge Tokens | 39204804 | 5 days ago | IN | 0.00004944 ETH | 0.00000039 | ||||
| Bridge Tokens | 39184657 | 6 days ago | IN | 0.00004944 ETH | 0.00000067 | ||||
| Bridge Tokens | 39184632 | 6 days ago | IN | 0.00004944 ETH | 0.0000007 | ||||
| Bridge Tokens | 38504716 | 22 days ago | IN | 0.00005138 ETH | 0.00000082 | ||||
| Bridge Tokens | 37773586 | 39 days ago | IN | 0.00004323 ETH | 0.00001188 | ||||
| Bridge Tokens | 37707151 | 40 days ago | IN | 0.00004058 ETH | 0.00000451 | ||||
| Bridge Tokens | 37564777 | 43 days ago | IN | 0.00003849 ETH | 0.00000667 | ||||
| Bridge Tokens | 37563410 | 43 days ago | IN | 0.00003849 ETH | 0.00003051 | ||||
| Bridge Tokens | 36902386 | 59 days ago | IN | 0.00003467 ETH | 0.00000388 | ||||
| Bridge Tokens | 36708638 | 63 days ago | IN | 0.00003632 ETH | 0.00000095 | ||||
| Bridge Tokens | 36558012 | 67 days ago | IN | 0.00003137 ETH | 0.00000127 | ||||
| Bridge Tokens | 36552428 | 67 days ago | IN | 0.0003 ETH | 0.00000204 | ||||
| Bridge Tokens | 36469664 | 69 days ago | IN | 0.00003274 ETH | 0.00000063 | ||||
| Bridge Tokens | 36462856 | 69 days ago | IN | 0.00003274 ETH | 0.00000367 | ||||
| Bridge Tokens | 36461111 | 69 days ago | IN | 0.00003274 ETH | 0.00000236 | ||||
| Bridge Tokens | 36457647 | 69 days ago | IN | 0.00003274 ETH | 0.00000079 | ||||
| Bridge Tokens | 36457262 | 69 days ago | IN | 0.00003274 ETH | 0.00000217 | ||||
| Bridge Tokens | 36457172 | 69 days ago | IN | 0.00003274 ETH | 0.00000019 | ||||
| Bridge Tokens | 36457167 | 69 days ago | IN | 0.00003274 ETH | 0.00000119 | ||||
| Bridge Tokens | 36456976 | 69 days ago | IN | 0.00003274 ETH | 0.00000126 | ||||
| Bridge Tokens | 36456884 | 69 days ago | IN | 0.00003274 ETH | 0.00000017 | ||||
| Bridge Tokens | 36456878 | 69 days ago | IN | 0.00003274 ETH | 0.00000109 | ||||
| Bridge Tokens | 36426687 | 70 days ago | IN | 0.00003274 ETH | 0.00000073 | ||||
| Bridge Tokens | 36399574 | 70 days ago | IN | 0.00003274 ETH | 0.00000099 | ||||
| Bridge Tokens | 36209866 | 75 days ago | IN | 0.00003413 ETH | 0.00000113 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 39204804 | 5 days ago | 0.00004944 ETH | ||||
| 39184657 | 6 days ago | 0.00004944 ETH | ||||
| 39184632 | 6 days ago | 0.00004944 ETH | ||||
| 38504716 | 22 days ago | 0.00005138 ETH | ||||
| 37773586 | 39 days ago | 0.00004323 ETH | ||||
| 37707151 | 40 days ago | 0.00004058 ETH | ||||
| 37564777 | 43 days ago | 0.00003849 ETH | ||||
| 37563410 | 43 days ago | 0.00003849 ETH | ||||
| 36902386 | 59 days ago | 0.00003467 ETH | ||||
| 36708638 | 63 days ago | 0.00003632 ETH | ||||
| 36558012 | 67 days ago | 0.00003137 ETH | ||||
| 36552428 | 67 days ago | 0.0003 ETH | ||||
| 36469664 | 69 days ago | 0.00003274 ETH | ||||
| 36462856 | 69 days ago | 0.00003274 ETH | ||||
| 36461111 | 69 days ago | 0.00003274 ETH | ||||
| 36457647 | 69 days ago | 0.00003274 ETH | ||||
| 36457262 | 69 days ago | 0.00003274 ETH | ||||
| 36457167 | 69 days ago | 0.00003274 ETH | ||||
| 36456976 | 69 days ago | 0.00003274 ETH | ||||
| 36456878 | 69 days ago | 0.00003274 ETH | ||||
| 36426687 | 70 days ago | 0.00003274 ETH | ||||
| 36399574 | 70 days ago | 0.00003274 ETH | ||||
| 36209866 | 75 days ago | 0.00003413 ETH | ||||
| 35989633 | 80 days ago | 0.00003401 ETH | ||||
| 35514837 | 91 days ago | 0.00003207 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EtaBridge
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
contract EtaBridge is OApp, ReentrancyGuard {
mapping(string => IERC20Metadata) public supportedTokens;
uint16 public feeBasisPoints;
uint256 private immutable scale = 1e18;
uint16 private immutable maxFeeBasisPoints = 100; // 1%
event TokensBridged(bytes32 indexed guid, address indexed sender, IERC20Metadata token, uint256 amount, address receiver, uint256 fee, uint32 targetChainId);
event TokensReleased(bytes32 indexed guid, address indexed receiver, IERC20Metadata token, uint256 amount);
event TokenAdded(string indexed symbol, IERC20Metadata indexed tokenAddress);
event TokenRemoved(string indexed symbol);
event FeeUpdated(uint16 indexed feeBasisPoints);
error TokenNotSupported(string symbol);
error FeeExceedMaximum(uint16 feeBasisPoints, uint16 maxFeeBasisPoints);
error InvalidReceiverAddress();
constructor(address _owner, address _lzEndpoint, uint16 _feeBasisPoints) Ownable(_owner) OApp(_lzEndpoint, _owner) {
if (_feeBasisPoints > 100) revert FeeExceedMaximum(_feeBasisPoints, maxFeeBasisPoints);
feeBasisPoints = _feeBasisPoints;
}
function addSupportedToken(string calldata _symbol, IERC20Metadata _address) external onlyOwner {
supportedTokens[_symbol] = _address;
emit TokenAdded(_symbol, _address);
}
function removeSupportedToken(string calldata _symbol) external onlyOwner {
if (address(supportedTokens[_symbol]) == address(0)) revert TokenNotSupported(_symbol);
delete supportedTokens[_symbol];
emit TokenRemoved(_symbol);
}
function updateFee(uint16 _feeBasisPoints) external onlyOwner {
if (_feeBasisPoints > 100) revert FeeExceedMaximum(_feeBasisPoints, maxFeeBasisPoints);
feeBasisPoints = _feeBasisPoints;
emit FeeUpdated(_feeBasisPoints);
}
function quote(
string calldata symbol,
uint256 amount,
address receiver,
uint32 targetChainId,
bytes calldata _options
) public view returns (uint256 nativeFee) {
if (receiver == address(0)) revert InvalidReceiverAddress();
IERC20Metadata token = supportedTokens[symbol];
if (address(token) == address(0)) revert TokenNotSupported(symbol);
(uint256 amountAfterFee,) = _calculateAmountsToSend(token, amount);
bytes memory payload = abi.encode(receiver, symbol, amountAfterFee);
MessagingFee memory estimate = _quote(targetChainId, payload, _options, false);
return estimate.nativeFee;
}
function bridgeTokens(
string calldata symbol,
uint256 amount,
address receiver,
uint32 targetChainId,
bytes calldata _options
) external payable nonReentrant returns (MessagingReceipt memory receipt) {
if (receiver == address(0)) revert InvalidReceiverAddress();
IERC20Metadata token = supportedTokens[symbol];
if (address(token) == address(0)) revert TokenNotSupported(symbol);
uint256 transferredAmount = 0;
{
uint256 balanceBefore = token.balanceOf(address(this));
SafeERC20.safeTransferFrom(token, msg.sender, address(this), amount);
uint256 balanceAfter = token.balanceOf(address(this));
transferredAmount = balanceAfter - balanceBefore;
}
(uint256 amountAfterFee, uint256 fee) = _calculateAmountsToSend(token, transferredAmount);
bytes memory payload = abi.encode(receiver, symbol, amountAfterFee);
receipt = _lzSend(targetChainId, payload, _options, MessagingFee(msg.value, 0), payable(msg.sender));
emit TokensBridged(receipt.guid, msg.sender, token, amountAfterFee, receiver, fee, targetChainId);
}
function _calculateAmountsToSend(IERC20Metadata token, uint256 amount) private view returns (uint256 amountAfterFee, uint256 fee) {
uint256 normalizedAmount = (amount * scale) / (10 ** token.decimals());
fee = (normalizedAmount * feeBasisPoints) / 10000;
amountAfterFee = normalizedAmount - fee;
}
function _lzReceive(
Origin calldata,
bytes32 guid,
bytes calldata payload,
address,
bytes calldata
) internal override nonReentrant {
(address receiver, string memory symbol, uint256 amount) = abi.decode(payload, (address, string, uint256));
IERC20Metadata token = supportedTokens[symbol];
if (address(token) == address(0)) revert TokenNotSupported(symbol);
uint256 normalizedAmount = (amount * (10 ** token.decimals())) / scale;
emit TokensReleased(guid, receiver, token, normalizedAmount);
SafeERC20.safeTransfer(token, receiver, normalizedAmount);
}
// Recover ERC20 tokens sent to this contract
function recoverERC20(IERC20 tokenAddress, uint256 amount) external onlyOwner {
SafeERC20.safeTransfer(tokenAddress, owner(), amount);
}
// Recover native currency sent to this contract via specific functions
function recoverNative() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the 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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.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 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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCore is IOAppCore, Ownable {
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
// Mapping to store peers associated with corresponding endpoints
mapping(uint32 eid => bytes32 peer) public peers;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*
* @dev The delegate typically should be set as the owner of the contract.
*/
constructor(address _endpoint, address _delegate) {
endpoint = ILayerZeroEndpointV2(_endpoint);
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
_setPeer(_eid, _peer);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
peers[_eid] = _peer;
emit PeerSet(_eid, _peer);
}
/**
* @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
* ie. the peer is set to bytes32(0).
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
bytes32 peer = peers[_eid];
if (peer == bytes32(0)) revert NoPeer(_eid);
return peer;
}
/**
* @notice Sets the delegate address for the OApp.
* @param _delegate The address of the delegate to be set.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
*/
function setDelegate(address _delegate) public onlyOwner {
endpoint.setDelegate(_delegate);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
// Custom error message for when the caller is not the registered endpoint/
error OnlyEndpoint(address addr);
// @dev The version of the OAppReceiver implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant RECEIVER_VERSION = 2;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
* ie. this is a RECEIVE only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (0, RECEIVER_VERSION);
}
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @dev _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @dev _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata /*_origin*/,
bytes calldata /*_message*/,
address _sender
) public view virtual returns (bool) {
return _sender == address(this);
}
/**
* @notice Checks if the path initialization is allowed based on the provided origin.
* @param origin The origin information containing the source endpoint and sender address.
* @return Whether the path has been initialized.
*
* @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
* @dev This defaults to assuming if a peer has been set, its initialized.
* Can be overridden by the OApp if there is other logic to determine this.
*/
function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
return peers[origin.srcEid] == origin.sender;
}
/**
* @notice Retrieves the next nonce for a given source endpoint and sender address.
* @dev _srcEid The source endpoint ID.
* @dev _sender The sender address.
* @return nonce The next nonce.
*
* @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
* @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
* @dev This is also enforced by the OApp.
* @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
*/
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
return 0;
}
/**
* @dev Entry point for receiving messages or packets from the endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The payload of the received message.
* @param _executor The address of the executor for the received message.
* @param _extraData Additional arbitrary data provided by the corresponding executor.
*
* @dev Entry point for receiving msg/packet from the LayerZero endpoint.
*/
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) public payable virtual {
// Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
// Ensure that the sender matches the expected peer for the source endpoint.
if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
// Call the internal OApp implementation of lzReceive.
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSender is OAppCore {
using SafeERC20 for IERC20;
// Custom error messages
error NotEnoughNative(uint256 msgValue);
error LzTokenUnavailable();
// @dev The version of the OAppSender implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant SENDER_VERSION = 1;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
* ie. this is a SEND only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (SENDER_VERSION, 0);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
* @return fee The calculated MessagingFee for the message.
* - nativeFee: The native fee for the message.
* - lzTokenFee: The LZ token fee for the message.
*/
function _quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
bool _payInLzToken
) internal view virtual returns (MessagingFee memory fee) {
return
endpoint.quote(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
address(this)
);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _fee The calculated LayerZero fee for the message.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess fee values sent to the endpoint.
* @return receipt The receipt for the sent message.
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _lzSend(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
MessagingFee memory _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory receipt) {
// @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
uint256 messageValue = _payNative(_fee.nativeFee);
if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
return
// solhint-disable-next-line check-send-result
endpoint.send{ value: messageValue }(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
_refundAddress
);
}
/**
* @dev Internal function to pay the native fee associated with the message.
* @param _nativeFee The native fee to be paid.
* @return nativeFee The amount of native currency paid.
*
* @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
* this will need to be overridden because msg.value would contain multiple lzFees.
* @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
* @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
* @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
*/
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
return _nativeFee;
}
/**
* @dev Internal function to pay the LZ token fee associated with the message.
* @param _lzTokenFee The LZ token fee to be paid.
*
* @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
* @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
*/
function _payLzToken(uint256 _lzTokenFee) internal virtual {
// @dev Cannot cache the token because it is not immutable in the endpoint.
address lzToken = endpoint.lzToken();
if (lzToken == address(0)) revert LzTokenUnavailable();
// Pay LZ token fee by sending tokens to the endpoint.
IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";
struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}
struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}
struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}
struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}
interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
event PacketDelivered(Origin origin, address receiver);
event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
event LzTokenSet(address token);
event DelegateSet(address sender, address delegate);
function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
function setLzToken(address _lzToken) external;
function lzToken() external view returns (address);
function nativeToken() external view returns (address);
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";
interface IOAppReceiver is ILayerZeroReceiver {
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata _origin,
bytes calldata _message,
address _sender
) external view returns (bool isSender);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @title IOAppCore
*/
interface IOAppCore {
// Custom error messages
error OnlyPeer(uint32 eid, bytes32 sender);
error NoPeer(uint32 eid);
error InvalidEndpointCall();
error InvalidDelegate();
// Event emitted when a peer (OApp) is set for a corresponding endpoint
event PeerSet(uint32 eid, bytes32 peer);
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*/
function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
/**
* @notice Retrieves the LayerZero endpoint associated with the OApp.
* @return iEndpoint The LayerZero endpoint as an interface.
*/
function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
/**
* @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
* @param _eid The endpoint ID.
* @return peer The peer address (OApp instance) associated with the corresponding endpoint.
*/
function peers(uint32 _eid) external view returns (bytes32 peer);
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*/
function setPeer(uint32 _eid, bytes32 _peer) external;
/**
* @notice Sets the delegate address for the OApp Core.
* @param _delegate The address of the delegate to be set.
*/
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "./ILayerZeroEndpointV2.sol";
interface ILayerZeroReceiver {
function allowInitializePath(Origin calldata _origin) external view returns (bool);
function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingChannel {
event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
function eid() external view returns (uint32);
// this is an emergency function if a message cannot be verified for some reasons
// required to provide _nextNonce to avoid race condition
function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
function inboundPayloadHash(
address _receiver,
uint32 _srcEid,
bytes32 _sender,
uint64 _nonce
) external view returns (bytes32);
function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingComposer {
event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
event LzComposeAlert(
address indexed from,
address indexed to,
address indexed executor,
bytes32 guid,
uint16 index,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
function composeQueue(
address _from,
address _to,
bytes32 _guid,
uint16 _index
) external view returns (bytes32 messageHash);
function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
struct SetConfigParam {
uint32 eid;
uint32 configType;
bytes config;
}
interface IMessageLibManager {
struct Timeout {
address lib;
uint256 expiry;
}
event LibraryRegistered(address newLib);
event DefaultSendLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
event SendLibrarySet(address sender, uint32 eid, address newLib);
event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
function registerLibrary(address _lib) external;
function isRegisteredLibrary(address _lib) external view returns (bool);
function getRegisteredLibraries() external view returns (address[] memory);
function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
function defaultSendLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function defaultReceiveLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;
function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);
function isSupportedEid(uint32 _eid) external view returns (bool);
function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);
/// ------------------- OApp interfaces -------------------
function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;
function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);
function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);
function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);
function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;
function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);
function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;
function getConfig(
address _oapp,
address _lib,
uint32 _eid,
uint32 _configType
) external view returns (bytes memory config);
}{
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"remappings": []
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"uint16","name":"_feeBasisPoints","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint16","name":"feeBasisPoints","type":"uint16"},{"internalType":"uint16","name":"maxFeeBasisPoints","type":"uint16"}],"name":"FeeExceedMaximum","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidReceiverAddress","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"}],"name":"TokenNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"feeBasisPoints","type":"uint16"}],"name":"FeeUpdated","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":true,"internalType":"string","name":"symbol","type":"string"},{"indexed":true,"internalType":"contract IERC20Metadata","name":"tokenAddress","type":"address"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"symbol","type":"string"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"targetChainId","type":"uint32"}],"name":"TokensBridged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensReleased","type":"event"},{"inputs":[{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"contract IERC20Metadata","name":"_address","type":"address"}],"name":"addSupportedToken","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":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint32","name":"targetChainId","type":"uint32"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"bridgeTokens","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":"receipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBasisPoints","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","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":[{"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":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint32","name":"targetChainId","type":"uint32"},{"internalType":"bytes","name":"_options","type":"bytes"}],"name":"quote","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"removeSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","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":"string","name":"","type":"string"}],"name":"supportedTokens","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBasisPoints","type":"uint16"}],"name":"updateFee","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e0604052670de0b6b3a764000060a090815250606461ffff1660c09061ffff1681525034801561002e575f80fd5b506040516133fc3803806133fc833981810160405281019061005091906103aa565b81838181865f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100bc9190610409565b60405180910390fd5b6100d48161025460201b60201c565b508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361016e576040517fb586360400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60805173ffffffffffffffffffffffffffffffffffffffff1663ca5eb5e1826040518263ffffffff1660e01b81526004016101a99190610409565b5f604051808303815f87803b1580156101c0575f80fd5b505af11580156101d2573d5f803e3d5ffd5b5050505050505050600160028190555060648161ffff161115610230578060c0516040517f809236c6000000000000000000000000000000000000000000000000000000008152600401610227929190610431565b60405180910390fd5b8060045f6101000a81548161ffff021916908361ffff160217905550505050610458565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61034282610319565b9050919050565b61035281610338565b811461035c575f80fd5b50565b5f8151905061036d81610349565b92915050565b5f61ffff82169050919050565b61038981610373565b8114610393575f80fd5b50565b5f815190506103a481610380565b92915050565b5f805f606084860312156103c1576103c0610315565b5b5f6103ce8682870161035f565b93505060206103df8682870161035f565b92505060406103f086828701610396565b9150509250925092565b61040381610338565b82525050565b5f60208201905061041c5f8301846103fa565b92915050565b61042b81610373565b82525050565b5f6040820190506104445f830185610422565b6104516020830184610422565b9392505050565b60805160a05160c051612f496104b35f395f61061401525f81816111ff01526115c401525f81816104e70152818161072d015281816109a50152818161164801528181611818015281816119f70152611aef0152612f495ff3fe608060405260043610610129575f3560e01c806389919cdd116100aa578063ca5eb5e11161006e578063ca5eb5e1146103ae578063e4f33b48146103d6578063e97653dd14610412578063ed88ed6c14610442578063f2fde38b1461046a578063ff7bd03d1461049257610129565b806389919cdd146102ba5780638da5cb5b146102f657806392543a8a14610320578063b8606eef14610348578063bb0b6a531461037257610129565b80635e280f11116100f15780635e280f11146101da578063715018a6146102045780637d25a05e1461021a57806382413eac146102565780638980f11f1461029257610129565b806313137d651461012d57806317442b70146101495780632c6cda93146101745780633400288b1461019c5780635a54db86146101c4575b5f80fd5b61014760048036038101906101429190611ca5565b6104ce565b005b348015610154575f80fd5b5061015d6105ee565b60405161016b929190611d7e565b60405180910390f35b34801561017f575f80fd5b5061019a60048036038101906101959190611ddc565b6105fc565b005b3480156101a7575f80fd5b506101c260048036038101906101bd9190611e40565b6106c0565b005b3480156101cf575f80fd5b506101d86106d6565b005b3480156101e5575f80fd5b506101ee61072b565b6040516101fb9190611ed9565b60405180910390f35b34801561020f575f80fd5b5061021861074f565b005b348015610225575f80fd5b50610240600480360381019061023b9190611e40565b610762565b60405161024d9190611ef2565b60405180910390f35b348015610261575f80fd5b5061027c60048036038101906102779190611f0b565b610769565b6040516102899190611f96565b60405180910390f35b34801561029d575f80fd5b506102b860048036038101906102b3919061201d565b6107a3565b005b3480156102c5575f80fd5b506102e060048036038101906102db9190612193565b6107c1565b6040516102ed91906121fa565b60405180910390f35b348015610301575f80fd5b5061030a610809565b6040516103179190612222565b60405180910390f35b34801561032b575f80fd5b5061034660048036038101906103419190612290565b610830565b005b348015610353575f80fd5b5061035c610973565b60405161036991906122ea565b60405180910390f35b34801561037d575f80fd5b5061039860048036038101906103939190612303565b610986565b6040516103a5919061233d565b60405180910390f35b3480156103b9575f80fd5b506103d460048036038101906103cf9190612356565b61099b565b005b3480156103e1575f80fd5b506103fc60048036038101906103f79190612381565b610a2c565b6040516104099190612447565b60405180910390f35b61042c60048036038101906104279190612381565b610be5565b60405161043991906124fa565b60405180910390f35b34801561044d575f80fd5b506104686004803603810190610463919061254e565b610f33565b005b348015610475575f80fd5b50610490600480360381019061048b9190612356565b610ff9565b005b34801561049d575f80fd5b506104b860048036038101906104b391906125ab565b61107d565b6040516104c59190611f96565b60405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161461055e57336040517f91ac5e4f0000000000000000000000000000000000000000000000000000000081526004016105559190612222565b60405180910390fd5b866020013561057d885f0160208101906105789190612303565b6110ba565b146105d657865f0160208101906105949190612303565b87602001356040517fc26bebcc0000000000000000000000000000000000000000000000000000000081526004016105cd9291906125e5565b60405180910390fd5b6105e58787878787878761112b565b50505050505050565b5f8060016002915091509091565b610604611320565b60648161ffff16111561067057807f00000000000000000000000000000000000000000000000000000000000000006040517f809236c600000000000000000000000000000000000000000000000000000000815260040161066792919061260c565b60405180910390fd5b8060045f6101000a81548161ffff021916908361ffff1602179055508061ffff167fc8fcf8ee1425e7e60b8af83735e1eb516d5b9ef05bfd6eece552ebaeb7c75b4860405160405180910390a250565b6106c8611320565b6106d282826113a7565b5050565b6106de611320565b6106e6610809565b73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610728573d5f803e3d5ffd5b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b610757611320565b6107605f611406565b565b5f92915050565b5f3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050949350505050565b6107ab611320565b6107bd826107b7610809565b836114c7565b5050565b6003818051602081018201805184825260208301602085012081835280955050505050505f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610838611320565b5f73ffffffffffffffffffffffffffffffffffffffff1660038383604051610861929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036108e95781816040517fc16fc3ad0000000000000000000000000000000000000000000000000000000081526004016108e09291906126b5565b60405180910390fd5b600382826040516108fb929190612661565b90815260200160405180910390205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055818160405161093b929190612661565b60405180910390207fcdd02d37d444f381ccea186dcdaf556989dcdeeebafc5cd307fe5e7609cd88c360405160405180910390a25050565b60045f9054906101000a900461ffff1681565b6001602052805f5260405f205f915090505481565b6109a3611320565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ca5eb5e1826040518263ffffffff1660e01b81526004016109fc9190612222565b5f604051808303815f87803b158015610a13575f80fd5b505af1158015610a25573d5f803e3d5ffd5b5050505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610a92576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60038989604051610aa5929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b475788886040517fc16fc3ad000000000000000000000000000000000000000000000000000000008152600401610b3e9291906126b5565b60405180910390fd5b5f610b528289611546565b5090505f878b8b84604051602001610b6d94939291906126d7565b60405160208183030381529060405290505f610bce888389898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050505f61163e565b9050805f0151945050505050979650505050505050565b610bed611b3a565b610bf561171f565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c5a576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60038989604051610c6d929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d0f5788886040517fc16fc3ad000000000000000000000000000000000000000000000000000000008152600401610d069291906126b5565b60405180910390fd5b5f808273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d4a9190612222565b602060405180830381865afa158015610d65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d899190612729565b9050610d978333308c611763565b5f8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610dd19190612222565b602060405180830381865afa158015610dec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e109190612729565b90508181610e1e9190612781565b925050505f80610e2e8484611546565b915091505f898d8d85604051602001610e4a94939291906126d7565b6040516020818303038152906040529050610ebf89828a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505060405180604001604052803481526020015f815250336117e5565b95503373ffffffffffffffffffffffffffffffffffffffff16865f01517fe1a7126622f5c308da3c5cc9757d65b49763c989099d8cd64171c17f51b702e287868e878f604051610f139594939291906127b4565b60405180910390a35050505050610f286118fb565b979650505050505050565b610f3b611320565b8060038484604051610f4e929190612661565b90815260200160405180910390205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff168383604051610fc0929190612661565b60405180910390207f6d97a31531bdb3c43d920bc996ec8b9fd7733f5f55a81cd74700f88631fc603260405160405180910390a3505050565b611001611320565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611071575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110689190612222565b60405180910390fd5b61107a81611406565b50565b5f816020013560015f845f0160208101906110989190612303565b63ffffffff1663ffffffff1681526020019081526020015f2054149050919050565b5f8060015f8463ffffffff1663ffffffff1681526020019081526020015f205490505f801b810361112257826040517ff6ff4fb70000000000000000000000000000000000000000000000000000000081526004016111199190612805565b60405180910390fd5b80915050919050565b61113361171f565b5f805f87878101906111459190612859565b9250925092505f60038360405161115c919061290d565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111fc57826040517fc16fc3ad0000000000000000000000000000000000000000000000000000000081526004016111f3919061295b565b60405180910390fd5b5f7f00000000000000000000000000000000000000000000000000000000000000008273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611267573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061128b91906129b1565b600a6112979190612b0b565b846112a29190612b55565b6112ac9190612bc3565b90508473ffffffffffffffffffffffffffffffffffffffff168b7f95d209edc2dd51498eb0f9b4c7fb85223de3a46f6a83e0aba5d2d0e9a0d7207784846040516112f7929190612bf3565b60405180910390a361130a8286836114c7565b50505050506113176118fb565b50505050505050565b611328611905565b73ffffffffffffffffffffffffffffffffffffffff16611346610809565b73ffffffffffffffffffffffffffffffffffffffff16146113a557611369611905565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161139c9190612222565b60405180910390fd5b565b8060015f8463ffffffff1663ffffffff1681526020019081526020015f20819055507f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b82826040516113fa9291906125e5565b60405180910390a15050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611541838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016114fa929190612c1a565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061190c565b505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611592573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b691906129b1565b600a6115c29190612b0b565b7f0000000000000000000000000000000000000000000000000000000000000000856115ee9190612b55565b6115f89190612bc3565b905061271060045f9054906101000a900461ffff1661ffff168261161c9190612b55565b6116269190612bc3565b915081816116349190612781565b9250509250929050565b611646611b6c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ddc28c586040518060a001604052808863ffffffff1681526020016116a2896110ba565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b81526004016116d7929190612d2b565b6040805180830381865afa1580156116f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117159190612daa565b9050949350505050565b600280540361175a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028081905550565b6117df848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161179893929190612dd5565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061190c565b50505050565b6117ed611b3a565b5f6117fa845f01516119a7565b90505f846020015111156118165761181584602001516119f4565b5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632637a450826040518060a001604052808b63ffffffff1681526020016118738c6110ba565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b81526004016118ae929190612d2b565b60806040518083038185885af11580156118ca573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906118ef9190612ea9565b91505095945050505050565b6001600281905550565b5f33905090565b5f8060205f8451602086015f885af18061192b576040513d5f823e3d81fd5b3d92505f519150505f821461194457600181141561195f565b5f8473ffffffffffffffffffffffffffffffffffffffff163b145b156119a157836040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016119989190612222565b60405180910390fd5b50505050565b5f8134146119ec57346040517f9f7041200000000000000000000000000000000000000000000000000000000081526004016119e39190612447565b60405180910390fd5b819050919050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a829190612ee8565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ae9576040517f5373352a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b36337f0000000000000000000000000000000000000000000000000000000000000000848473ffffffffffffffffffffffffffffffffffffffff16611763909392919063ffffffff16565b5050565b60405180606001604052805f80191681526020015f67ffffffffffffffff168152602001611b66611b6c565b81525090565b60405180604001604052805f81526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f60608284031215611bae57611bad611b95565b5b81905092915050565b5f819050919050565b611bc981611bb7565b8114611bd3575f80fd5b50565b5f81359050611be481611bc0565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112611c0b57611c0a611bea565b5b8235905067ffffffffffffffff811115611c2857611c27611bee565b5b602083019150836001820283011115611c4457611c43611bf2565b5b9250929050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611c7482611c4b565b9050919050565b611c8481611c6a565b8114611c8e575f80fd5b50565b5f81359050611c9f81611c7b565b92915050565b5f805f805f805f60e0888a031215611cc057611cbf611b8d565b5b5f611ccd8a828b01611b99565b9750506060611cde8a828b01611bd6565b965050608088013567ffffffffffffffff811115611cff57611cfe611b91565b5b611d0b8a828b01611bf6565b955095505060a0611d1e8a828b01611c91565b93505060c088013567ffffffffffffffff811115611d3f57611d3e611b91565b5b611d4b8a828b01611bf6565b925092505092959891949750929550565b5f67ffffffffffffffff82169050919050565b611d7881611d5c565b82525050565b5f604082019050611d915f830185611d6f565b611d9e6020830184611d6f565b9392505050565b5f61ffff82169050919050565b611dbb81611da5565b8114611dc5575f80fd5b50565b5f81359050611dd681611db2565b92915050565b5f60208284031215611df157611df0611b8d565b5b5f611dfe84828501611dc8565b91505092915050565b5f63ffffffff82169050919050565b611e1f81611e07565b8114611e29575f80fd5b50565b5f81359050611e3a81611e16565b92915050565b5f8060408385031215611e5657611e55611b8d565b5b5f611e6385828601611e2c565b9250506020611e7485828601611bd6565b9150509250929050565b5f819050919050565b5f611ea1611e9c611e9784611c4b565b611e7e565b611c4b565b9050919050565b5f611eb282611e87565b9050919050565b5f611ec382611ea8565b9050919050565b611ed381611eb9565b82525050565b5f602082019050611eec5f830184611eca565b92915050565b5f602082019050611f055f830184611d6f565b92915050565b5f805f8060a08587031215611f2357611f22611b8d565b5b5f611f3087828801611b99565b945050606085013567ffffffffffffffff811115611f5157611f50611b91565b5b611f5d87828801611bf6565b93509350506080611f7087828801611c91565b91505092959194509250565b5f8115159050919050565b611f9081611f7c565b82525050565b5f602082019050611fa95f830184611f87565b92915050565b5f611fb982611c6a565b9050919050565b611fc981611faf565b8114611fd3575f80fd5b50565b5f81359050611fe481611fc0565b92915050565b5f819050919050565b611ffc81611fea565b8114612006575f80fd5b50565b5f8135905061201781611ff3565b92915050565b5f806040838503121561203357612032611b8d565b5b5f61204085828601611fd6565b925050602061205185828601612009565b9150509250929050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6120a58261205f565b810181811067ffffffffffffffff821117156120c4576120c361206f565b5b80604052505050565b5f6120d6611b84565b90506120e2828261209c565b919050565b5f67ffffffffffffffff8211156121015761210061206f565b5b61210a8261205f565b9050602081019050919050565b828183375f83830152505050565b5f612137612132846120e7565b6120cd565b9050828152602081018484840111156121535761215261205b565b5b61215e848285612117565b509392505050565b5f82601f83011261217a57612179611bea565b5b813561218a848260208601612125565b91505092915050565b5f602082840312156121a8576121a7611b8d565b5b5f82013567ffffffffffffffff8111156121c5576121c4611b91565b5b6121d184828501612166565b91505092915050565b5f6121e482611ea8565b9050919050565b6121f4816121da565b82525050565b5f60208201905061220d5f8301846121eb565b92915050565b61221c81611c6a565b82525050565b5f6020820190506122355f830184612213565b92915050565b5f8083601f8401126122505761224f611bea565b5b8235905067ffffffffffffffff81111561226d5761226c611bee565b5b60208301915083600182028301111561228957612288611bf2565b5b9250929050565b5f80602083850312156122a6576122a5611b8d565b5b5f83013567ffffffffffffffff8111156122c3576122c2611b91565b5b6122cf8582860161223b565b92509250509250929050565b6122e481611da5565b82525050565b5f6020820190506122fd5f8301846122db565b92915050565b5f6020828403121561231857612317611b8d565b5b5f61232584828501611e2c565b91505092915050565b61233781611bb7565b82525050565b5f6020820190506123505f83018461232e565b92915050565b5f6020828403121561236b5761236a611b8d565b5b5f61237884828501611c91565b91505092915050565b5f805f805f805f60a0888a03121561239c5761239b611b8d565b5b5f88013567ffffffffffffffff8111156123b9576123b8611b91565b5b6123c58a828b0161223b565b975097505060206123d88a828b01612009565b95505060406123e98a828b01611c91565b94505060606123fa8a828b01611e2c565b935050608088013567ffffffffffffffff81111561241b5761241a611b91565b5b6124278a828b01611bf6565b925092505092959891949750929550565b61244181611fea565b82525050565b5f60208201905061245a5f830184612438565b92915050565b61246981611bb7565b82525050565b61247881611d5c565b82525050565b61248781611fea565b82525050565b604082015f8201516124a15f85018261247e565b5060208201516124b4602085018261247e565b50505050565b608082015f8201516124ce5f850182612460565b5060208201516124e1602085018261246f565b5060408201516124f4604085018261248d565b50505050565b5f60808201905061250d5f8301846124ba565b92915050565b5f61251d82611c6a565b9050919050565b61252d81612513565b8114612537575f80fd5b50565b5f8135905061254881612524565b92915050565b5f805f6040848603121561256557612564611b8d565b5b5f84013567ffffffffffffffff81111561258257612581611b91565b5b61258e8682870161223b565b935093505060206125a18682870161253a565b9150509250925092565b5f606082840312156125c0576125bf611b8d565b5b5f6125cd84828501611b99565b91505092915050565b6125df81611e07565b82525050565b5f6040820190506125f85f8301856125d6565b612605602083018461232e565b9392505050565b5f60408201905061261f5f8301856122db565b61262c60208301846122db565b9392505050565b5f81905092915050565b5f6126488385612633565b9350612655838584612117565b82840190509392505050565b5f61266d82848661263d565b91508190509392505050565b5f82825260208201905092915050565b5f6126948385612679565b93506126a1838584612117565b6126aa8361205f565b840190509392505050565b5f6020820190508181035f8301526126ce818486612689565b90509392505050565b5f6060820190506126ea5f830187612213565b81810360208301526126fd818587612689565b905061270c6040830184612438565b95945050505050565b5f8151905061272381611ff3565b92915050565b5f6020828403121561273e5761273d611b8d565b5b5f61274b84828501612715565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61278b82611fea565b915061279683611fea565b92508282039050818111156127ae576127ad612754565b5b92915050565b5f60a0820190506127c75f8301886121eb565b6127d46020830187612438565b6127e16040830186612213565b6127ee6060830185612438565b6127fb60808301846125d6565b9695505050505050565b5f6020820190506128185f8301846125d6565b92915050565b5f61282882611c4b565b9050919050565b6128388161281e565b8114612842575f80fd5b50565b5f813590506128538161282f565b92915050565b5f805f606084860312156128705761286f611b8d565b5b5f61287d86828701612845565b935050602084013567ffffffffffffffff81111561289e5761289d611b91565b5b6128aa86828701612166565b92505060406128bb86828701612009565b9150509250925092565b5f81519050919050565b8281835e5f83830152505050565b5f6128e7826128c5565b6128f18185612633565b93506129018185602086016128cf565b80840191505092915050565b5f61291882846128dd565b915081905092915050565b5f61292d826128c5565b6129378185612679565b93506129478185602086016128cf565b6129508161205f565b840191505092915050565b5f6020820190508181035f8301526129738184612923565b905092915050565b5f60ff82169050919050565b6129908161297b565b811461299a575f80fd5b50565b5f815190506129ab81612987565b92915050565b5f602082840312156129c6576129c5611b8d565b5b5f6129d38482850161299d565b91505092915050565b5f8160011c9050919050565b5f808291508390505b6001851115612a3157808604811115612a0d57612a0c612754565b5b6001851615612a1c5780820291505b8081029050612a2a856129dc565b94506129f1565b94509492505050565b5f82612a495760019050612b04565b81612a56575f9050612b04565b8160018114612a6c5760028114612a7657612aa5565b6001915050612b04565b60ff841115612a8857612a87612754565b5b8360020a915084821115612a9f57612a9e612754565b5b50612b04565b5060208310610133831016604e8410600b8410161715612ada5782820a905083811115612ad557612ad4612754565b5b612b04565b612ae784848460016129e8565b92509050818404811115612afe57612afd612754565b5b81810290505b9392505050565b5f612b1582611fea565b9150612b208361297b565b9250612b4d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612a3a565b905092915050565b5f612b5f82611fea565b9150612b6a83611fea565b9250828202612b7881611fea565b91508282048414831517612b8f57612b8e612754565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612bcd82611fea565b9150612bd883611fea565b925082612be857612be7612b96565b5b828204905092915050565b5f604082019050612c065f8301856121eb565b612c136020830184612438565b9392505050565b5f604082019050612c2d5f830185612213565b612c3a6020830184612438565b9392505050565b612c4a81611e07565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f612c7482612c50565b612c7e8185612c5a565b9350612c8e8185602086016128cf565b612c978161205f565b840191505092915050565b612cab81611f7c565b82525050565b5f60a083015f830151612cc65f860182612c41565b506020830151612cd96020860182612460565b5060408301518482036040860152612cf18282612c6a565b91505060608301518482036060860152612d0b8282612c6a565b9150506080830151612d206080860182612ca2565b508091505092915050565b5f6040820190508181035f830152612d438185612cb1565b9050612d526020830184612213565b9392505050565b5f80fd5b5f60408284031215612d7257612d71612d59565b5b612d7c60406120cd565b90505f612d8b84828501612715565b5f830152506020612d9e84828501612715565b60208301525092915050565b5f60408284031215612dbf57612dbe611b8d565b5b5f612dcc84828501612d5d565b91505092915050565b5f606082019050612de85f830186612213565b612df56020830185612213565b612e026040830184612438565b949350505050565b5f81519050612e1881611bc0565b92915050565b612e2781611d5c565b8114612e31575f80fd5b50565b5f81519050612e4281612e1e565b92915050565b5f60808284031215612e5d57612e5c612d59565b5b612e6760606120cd565b90505f612e7684828501612e0a565b5f830152506020612e8984828501612e34565b6020830152506040612e9d84828501612d5d565b60408301525092915050565b5f60808284031215612ebe57612ebd611b8d565b5b5f612ecb84828501612e48565b91505092915050565b5f81519050612ee281611c7b565b92915050565b5f60208284031215612efd57612efc611b8d565b5b5f612f0a84828501612ed4565b9150509291505056fea264697066735822122065f854c363cf9ab14e4c280709db47ab5702824f21efdc503d67062adcf7216964736f6c634300081a0033000000000000000000000000615400b38307e4fff08b8f494da225b872c775300000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000000000000000000000000000000000000000001e
Deployed Bytecode
0x608060405260043610610129575f3560e01c806389919cdd116100aa578063ca5eb5e11161006e578063ca5eb5e1146103ae578063e4f33b48146103d6578063e97653dd14610412578063ed88ed6c14610442578063f2fde38b1461046a578063ff7bd03d1461049257610129565b806389919cdd146102ba5780638da5cb5b146102f657806392543a8a14610320578063b8606eef14610348578063bb0b6a531461037257610129565b80635e280f11116100f15780635e280f11146101da578063715018a6146102045780637d25a05e1461021a57806382413eac146102565780638980f11f1461029257610129565b806313137d651461012d57806317442b70146101495780632c6cda93146101745780633400288b1461019c5780635a54db86146101c4575b5f80fd5b61014760048036038101906101429190611ca5565b6104ce565b005b348015610154575f80fd5b5061015d6105ee565b60405161016b929190611d7e565b60405180910390f35b34801561017f575f80fd5b5061019a60048036038101906101959190611ddc565b6105fc565b005b3480156101a7575f80fd5b506101c260048036038101906101bd9190611e40565b6106c0565b005b3480156101cf575f80fd5b506101d86106d6565b005b3480156101e5575f80fd5b506101ee61072b565b6040516101fb9190611ed9565b60405180910390f35b34801561020f575f80fd5b5061021861074f565b005b348015610225575f80fd5b50610240600480360381019061023b9190611e40565b610762565b60405161024d9190611ef2565b60405180910390f35b348015610261575f80fd5b5061027c60048036038101906102779190611f0b565b610769565b6040516102899190611f96565b60405180910390f35b34801561029d575f80fd5b506102b860048036038101906102b3919061201d565b6107a3565b005b3480156102c5575f80fd5b506102e060048036038101906102db9190612193565b6107c1565b6040516102ed91906121fa565b60405180910390f35b348015610301575f80fd5b5061030a610809565b6040516103179190612222565b60405180910390f35b34801561032b575f80fd5b5061034660048036038101906103419190612290565b610830565b005b348015610353575f80fd5b5061035c610973565b60405161036991906122ea565b60405180910390f35b34801561037d575f80fd5b5061039860048036038101906103939190612303565b610986565b6040516103a5919061233d565b60405180910390f35b3480156103b9575f80fd5b506103d460048036038101906103cf9190612356565b61099b565b005b3480156103e1575f80fd5b506103fc60048036038101906103f79190612381565b610a2c565b6040516104099190612447565b60405180910390f35b61042c60048036038101906104279190612381565b610be5565b60405161043991906124fa565b60405180910390f35b34801561044d575f80fd5b506104686004803603810190610463919061254e565b610f33565b005b348015610475575f80fd5b50610490600480360381019061048b9190612356565b610ff9565b005b34801561049d575f80fd5b506104b860048036038101906104b391906125ab565b61107d565b6040516104c59190611f96565b60405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff167f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff161461055e57336040517f91ac5e4f0000000000000000000000000000000000000000000000000000000081526004016105559190612222565b60405180910390fd5b866020013561057d885f0160208101906105789190612303565b6110ba565b146105d657865f0160208101906105949190612303565b87602001356040517fc26bebcc0000000000000000000000000000000000000000000000000000000081526004016105cd9291906125e5565b60405180910390fd5b6105e58787878787878761112b565b50505050505050565b5f8060016002915091509091565b610604611320565b60648161ffff16111561067057807f00000000000000000000000000000000000000000000000000000000000000646040517f809236c600000000000000000000000000000000000000000000000000000000815260040161066792919061260c565b60405180910390fd5b8060045f6101000a81548161ffff021916908361ffff1602179055508061ffff167fc8fcf8ee1425e7e60b8af83735e1eb516d5b9ef05bfd6eece552ebaeb7c75b4860405160405180910390a250565b6106c8611320565b6106d282826113a7565b5050565b6106de611320565b6106e6610809565b73ffffffffffffffffffffffffffffffffffffffff166108fc4790811502906040515f60405180830381858888f19350505050158015610728573d5f803e3d5ffd5b50565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b610757611320565b6107605f611406565b565b5f92915050565b5f3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050949350505050565b6107ab611320565b6107bd826107b7610809565b836114c7565b5050565b6003818051602081018201805184825260208301602085012081835280955050505050505f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610838611320565b5f73ffffffffffffffffffffffffffffffffffffffff1660038383604051610861929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036108e95781816040517fc16fc3ad0000000000000000000000000000000000000000000000000000000081526004016108e09291906126b5565b60405180910390fd5b600382826040516108fb929190612661565b90815260200160405180910390205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055818160405161093b929190612661565b60405180910390207fcdd02d37d444f381ccea186dcdaf556989dcdeeebafc5cd307fe5e7609cd88c360405160405180910390a25050565b60045f9054906101000a900461ffff1681565b6001602052805f5260405f205f915090505481565b6109a3611320565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff1663ca5eb5e1826040518263ffffffff1660e01b81526004016109fc9190612222565b5f604051808303815f87803b158015610a13575f80fd5b505af1158015610a25573d5f803e3d5ffd5b5050505050565b5f8073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610a92576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60038989604051610aa5929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b475788886040517fc16fc3ad000000000000000000000000000000000000000000000000000000008152600401610b3e9291906126b5565b60405180910390fd5b5f610b528289611546565b5090505f878b8b84604051602001610b6d94939291906126d7565b60405160208183030381529060405290505f610bce888389898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050505f61163e565b9050805f0151945050505050979650505050505050565b610bed611b3a565b610bf561171f565b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610c5a576040517fa05ff47e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60038989604051610c6d929190612661565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d0f5788886040517fc16fc3ad000000000000000000000000000000000000000000000000000000008152600401610d069291906126b5565b60405180910390fd5b5f808273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d4a9190612222565b602060405180830381865afa158015610d65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d899190612729565b9050610d978333308c611763565b5f8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610dd19190612222565b602060405180830381865afa158015610dec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e109190612729565b90508181610e1e9190612781565b925050505f80610e2e8484611546565b915091505f898d8d85604051602001610e4a94939291906126d7565b6040516020818303038152906040529050610ebf89828a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505060405180604001604052803481526020015f815250336117e5565b95503373ffffffffffffffffffffffffffffffffffffffff16865f01517fe1a7126622f5c308da3c5cc9757d65b49763c989099d8cd64171c17f51b702e287868e878f604051610f139594939291906127b4565b60405180910390a35050505050610f286118fb565b979650505050505050565b610f3b611320565b8060038484604051610f4e929190612661565b90815260200160405180910390205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff168383604051610fc0929190612661565b60405180910390207f6d97a31531bdb3c43d920bc996ec8b9fd7733f5f55a81cd74700f88631fc603260405160405180910390a3505050565b611001611320565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611071575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016110689190612222565b60405180910390fd5b61107a81611406565b50565b5f816020013560015f845f0160208101906110989190612303565b63ffffffff1663ffffffff1681526020019081526020015f2054149050919050565b5f8060015f8463ffffffff1663ffffffff1681526020019081526020015f205490505f801b810361112257826040517ff6ff4fb70000000000000000000000000000000000000000000000000000000081526004016111199190612805565b60405180910390fd5b80915050919050565b61113361171f565b5f805f87878101906111459190612859565b9250925092505f60038360405161115c919061290d565b90815260200160405180910390205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111fc57826040517fc16fc3ad0000000000000000000000000000000000000000000000000000000081526004016111f3919061295b565b60405180910390fd5b5f7f0000000000000000000000000000000000000000000000000de0b6b3a76400008273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611267573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061128b91906129b1565b600a6112979190612b0b565b846112a29190612b55565b6112ac9190612bc3565b90508473ffffffffffffffffffffffffffffffffffffffff168b7f95d209edc2dd51498eb0f9b4c7fb85223de3a46f6a83e0aba5d2d0e9a0d7207784846040516112f7929190612bf3565b60405180910390a361130a8286836114c7565b50505050506113176118fb565b50505050505050565b611328611905565b73ffffffffffffffffffffffffffffffffffffffff16611346610809565b73ffffffffffffffffffffffffffffffffffffffff16146113a557611369611905565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161139c9190612222565b60405180910390fd5b565b8060015f8463ffffffff1663ffffffff1681526020019081526020015f20819055507f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b82826040516113fa9291906125e5565b60405180910390a15050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611541838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016114fa929190612c1a565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061190c565b505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611592573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b691906129b1565b600a6115c29190612b0b565b7f0000000000000000000000000000000000000000000000000de0b6b3a7640000856115ee9190612b55565b6115f89190612bc3565b905061271060045f9054906101000a900461ffff1661ffff168261161c9190612b55565b6116269190612bc3565b915081816116349190612781565b9250509250929050565b611646611b6c565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff1663ddc28c586040518060a001604052808863ffffffff1681526020016116a2896110ba565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b81526004016116d7929190612d2b565b6040805180830381865afa1580156116f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117159190612daa565b9050949350505050565b600280540361175a576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028081905550565b6117df848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161179893929190612dd5565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061190c565b50505050565b6117ed611b3a565b5f6117fa845f01516119a7565b90505f846020015111156118165761181584602001516119f4565b5b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff16632637a450826040518060a001604052808b63ffffffff1681526020016118738c6110ba565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b81526004016118ae929190612d2b565b60806040518083038185885af11580156118ca573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906118ef9190612ea9565b91505095945050505050565b6001600281905550565b5f33905090565b5f8060205f8451602086015f885af18061192b576040513d5f823e3d81fd5b3d92505f519150505f821461194457600181141561195f565b5f8473ffffffffffffffffffffffffffffffffffffffff163b145b156119a157836040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016119989190612222565b60405180910390fd5b50505050565b5f8134146119ec57346040517f9f7041200000000000000000000000000000000000000000000000000000000081526004016119e39190612447565b60405180910390fd5b819050919050565b5f7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff1663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a829190612ee8565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ae9576040517f5373352a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b36337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c848473ffffffffffffffffffffffffffffffffffffffff16611763909392919063ffffffff16565b5050565b60405180606001604052805f80191681526020015f67ffffffffffffffff168152602001611b66611b6c565b81525090565b60405180604001604052805f81526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f60608284031215611bae57611bad611b95565b5b81905092915050565b5f819050919050565b611bc981611bb7565b8114611bd3575f80fd5b50565b5f81359050611be481611bc0565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112611c0b57611c0a611bea565b5b8235905067ffffffffffffffff811115611c2857611c27611bee565b5b602083019150836001820283011115611c4457611c43611bf2565b5b9250929050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611c7482611c4b565b9050919050565b611c8481611c6a565b8114611c8e575f80fd5b50565b5f81359050611c9f81611c7b565b92915050565b5f805f805f805f60e0888a031215611cc057611cbf611b8d565b5b5f611ccd8a828b01611b99565b9750506060611cde8a828b01611bd6565b965050608088013567ffffffffffffffff811115611cff57611cfe611b91565b5b611d0b8a828b01611bf6565b955095505060a0611d1e8a828b01611c91565b93505060c088013567ffffffffffffffff811115611d3f57611d3e611b91565b5b611d4b8a828b01611bf6565b925092505092959891949750929550565b5f67ffffffffffffffff82169050919050565b611d7881611d5c565b82525050565b5f604082019050611d915f830185611d6f565b611d9e6020830184611d6f565b9392505050565b5f61ffff82169050919050565b611dbb81611da5565b8114611dc5575f80fd5b50565b5f81359050611dd681611db2565b92915050565b5f60208284031215611df157611df0611b8d565b5b5f611dfe84828501611dc8565b91505092915050565b5f63ffffffff82169050919050565b611e1f81611e07565b8114611e29575f80fd5b50565b5f81359050611e3a81611e16565b92915050565b5f8060408385031215611e5657611e55611b8d565b5b5f611e6385828601611e2c565b9250506020611e7485828601611bd6565b9150509250929050565b5f819050919050565b5f611ea1611e9c611e9784611c4b565b611e7e565b611c4b565b9050919050565b5f611eb282611e87565b9050919050565b5f611ec382611ea8565b9050919050565b611ed381611eb9565b82525050565b5f602082019050611eec5f830184611eca565b92915050565b5f602082019050611f055f830184611d6f565b92915050565b5f805f8060a08587031215611f2357611f22611b8d565b5b5f611f3087828801611b99565b945050606085013567ffffffffffffffff811115611f5157611f50611b91565b5b611f5d87828801611bf6565b93509350506080611f7087828801611c91565b91505092959194509250565b5f8115159050919050565b611f9081611f7c565b82525050565b5f602082019050611fa95f830184611f87565b92915050565b5f611fb982611c6a565b9050919050565b611fc981611faf565b8114611fd3575f80fd5b50565b5f81359050611fe481611fc0565b92915050565b5f819050919050565b611ffc81611fea565b8114612006575f80fd5b50565b5f8135905061201781611ff3565b92915050565b5f806040838503121561203357612032611b8d565b5b5f61204085828601611fd6565b925050602061205185828601612009565b9150509250929050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6120a58261205f565b810181811067ffffffffffffffff821117156120c4576120c361206f565b5b80604052505050565b5f6120d6611b84565b90506120e2828261209c565b919050565b5f67ffffffffffffffff8211156121015761210061206f565b5b61210a8261205f565b9050602081019050919050565b828183375f83830152505050565b5f612137612132846120e7565b6120cd565b9050828152602081018484840111156121535761215261205b565b5b61215e848285612117565b509392505050565b5f82601f83011261217a57612179611bea565b5b813561218a848260208601612125565b91505092915050565b5f602082840312156121a8576121a7611b8d565b5b5f82013567ffffffffffffffff8111156121c5576121c4611b91565b5b6121d184828501612166565b91505092915050565b5f6121e482611ea8565b9050919050565b6121f4816121da565b82525050565b5f60208201905061220d5f8301846121eb565b92915050565b61221c81611c6a565b82525050565b5f6020820190506122355f830184612213565b92915050565b5f8083601f8401126122505761224f611bea565b5b8235905067ffffffffffffffff81111561226d5761226c611bee565b5b60208301915083600182028301111561228957612288611bf2565b5b9250929050565b5f80602083850312156122a6576122a5611b8d565b5b5f83013567ffffffffffffffff8111156122c3576122c2611b91565b5b6122cf8582860161223b565b92509250509250929050565b6122e481611da5565b82525050565b5f6020820190506122fd5f8301846122db565b92915050565b5f6020828403121561231857612317611b8d565b5b5f61232584828501611e2c565b91505092915050565b61233781611bb7565b82525050565b5f6020820190506123505f83018461232e565b92915050565b5f6020828403121561236b5761236a611b8d565b5b5f61237884828501611c91565b91505092915050565b5f805f805f805f60a0888a03121561239c5761239b611b8d565b5b5f88013567ffffffffffffffff8111156123b9576123b8611b91565b5b6123c58a828b0161223b565b975097505060206123d88a828b01612009565b95505060406123e98a828b01611c91565b94505060606123fa8a828b01611e2c565b935050608088013567ffffffffffffffff81111561241b5761241a611b91565b5b6124278a828b01611bf6565b925092505092959891949750929550565b61244181611fea565b82525050565b5f60208201905061245a5f830184612438565b92915050565b61246981611bb7565b82525050565b61247881611d5c565b82525050565b61248781611fea565b82525050565b604082015f8201516124a15f85018261247e565b5060208201516124b4602085018261247e565b50505050565b608082015f8201516124ce5f850182612460565b5060208201516124e1602085018261246f565b5060408201516124f4604085018261248d565b50505050565b5f60808201905061250d5f8301846124ba565b92915050565b5f61251d82611c6a565b9050919050565b61252d81612513565b8114612537575f80fd5b50565b5f8135905061254881612524565b92915050565b5f805f6040848603121561256557612564611b8d565b5b5f84013567ffffffffffffffff81111561258257612581611b91565b5b61258e8682870161223b565b935093505060206125a18682870161253a565b9150509250925092565b5f606082840312156125c0576125bf611b8d565b5b5f6125cd84828501611b99565b91505092915050565b6125df81611e07565b82525050565b5f6040820190506125f85f8301856125d6565b612605602083018461232e565b9392505050565b5f60408201905061261f5f8301856122db565b61262c60208301846122db565b9392505050565b5f81905092915050565b5f6126488385612633565b9350612655838584612117565b82840190509392505050565b5f61266d82848661263d565b91508190509392505050565b5f82825260208201905092915050565b5f6126948385612679565b93506126a1838584612117565b6126aa8361205f565b840190509392505050565b5f6020820190508181035f8301526126ce818486612689565b90509392505050565b5f6060820190506126ea5f830187612213565b81810360208301526126fd818587612689565b905061270c6040830184612438565b95945050505050565b5f8151905061272381611ff3565b92915050565b5f6020828403121561273e5761273d611b8d565b5b5f61274b84828501612715565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61278b82611fea565b915061279683611fea565b92508282039050818111156127ae576127ad612754565b5b92915050565b5f60a0820190506127c75f8301886121eb565b6127d46020830187612438565b6127e16040830186612213565b6127ee6060830185612438565b6127fb60808301846125d6565b9695505050505050565b5f6020820190506128185f8301846125d6565b92915050565b5f61282882611c4b565b9050919050565b6128388161281e565b8114612842575f80fd5b50565b5f813590506128538161282f565b92915050565b5f805f606084860312156128705761286f611b8d565b5b5f61287d86828701612845565b935050602084013567ffffffffffffffff81111561289e5761289d611b91565b5b6128aa86828701612166565b92505060406128bb86828701612009565b9150509250925092565b5f81519050919050565b8281835e5f83830152505050565b5f6128e7826128c5565b6128f18185612633565b93506129018185602086016128cf565b80840191505092915050565b5f61291882846128dd565b915081905092915050565b5f61292d826128c5565b6129378185612679565b93506129478185602086016128cf565b6129508161205f565b840191505092915050565b5f6020820190508181035f8301526129738184612923565b905092915050565b5f60ff82169050919050565b6129908161297b565b811461299a575f80fd5b50565b5f815190506129ab81612987565b92915050565b5f602082840312156129c6576129c5611b8d565b5b5f6129d38482850161299d565b91505092915050565b5f8160011c9050919050565b5f808291508390505b6001851115612a3157808604811115612a0d57612a0c612754565b5b6001851615612a1c5780820291505b8081029050612a2a856129dc565b94506129f1565b94509492505050565b5f82612a495760019050612b04565b81612a56575f9050612b04565b8160018114612a6c5760028114612a7657612aa5565b6001915050612b04565b60ff841115612a8857612a87612754565b5b8360020a915084821115612a9f57612a9e612754565b5b50612b04565b5060208310610133831016604e8410600b8410161715612ada5782820a905083811115612ad557612ad4612754565b5b612b04565b612ae784848460016129e8565b92509050818404811115612afe57612afd612754565b5b81810290505b9392505050565b5f612b1582611fea565b9150612b208361297b565b9250612b4d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612a3a565b905092915050565b5f612b5f82611fea565b9150612b6a83611fea565b9250828202612b7881611fea565b91508282048414831517612b8f57612b8e612754565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612bcd82611fea565b9150612bd883611fea565b925082612be857612be7612b96565b5b828204905092915050565b5f604082019050612c065f8301856121eb565b612c136020830184612438565b9392505050565b5f604082019050612c2d5f830185612213565b612c3a6020830184612438565b9392505050565b612c4a81611e07565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f612c7482612c50565b612c7e8185612c5a565b9350612c8e8185602086016128cf565b612c978161205f565b840191505092915050565b612cab81611f7c565b82525050565b5f60a083015f830151612cc65f860182612c41565b506020830151612cd96020860182612460565b5060408301518482036040860152612cf18282612c6a565b91505060608301518482036060860152612d0b8282612c6a565b9150506080830151612d206080860182612ca2565b508091505092915050565b5f6040820190508181035f830152612d438185612cb1565b9050612d526020830184612213565b9392505050565b5f80fd5b5f60408284031215612d7257612d71612d59565b5b612d7c60406120cd565b90505f612d8b84828501612715565b5f830152506020612d9e84828501612715565b60208301525092915050565b5f60408284031215612dbf57612dbe611b8d565b5b5f612dcc84828501612d5d565b91505092915050565b5f606082019050612de85f830186612213565b612df56020830185612213565b612e026040830184612438565b949350505050565b5f81519050612e1881611bc0565b92915050565b612e2781611d5c565b8114612e31575f80fd5b50565b5f81519050612e4281612e1e565b92915050565b5f60808284031215612e5d57612e5c612d59565b5b612e6760606120cd565b90505f612e7684828501612e0a565b5f830152506020612e8984828501612e34565b6020830152506040612e9d84828501612d5d565b60408301525092915050565b5f60808284031215612ebe57612ebd611b8d565b5b5f612ecb84828501612e48565b91505092915050565b5f81519050612ee281611c7b565b92915050565b5f60208284031215612efd57612efc611b8d565b5b5f612f0a84828501612ed4565b9150509291505056fea264697066735822122065f854c363cf9ab14e4c280709db47ab5702824f21efdc503d67062adcf7216964736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000615400b38307e4fff08b8f494da225b872c775300000000000000000000000001a44076050125825900e736c501f859c50fe728c000000000000000000000000000000000000000000000000000000000000001e
-----Decoded View---------------
Arg [0] : _owner (address): 0x615400B38307e4Fff08b8f494da225b872C77530
Arg [1] : _lzEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [2] : _feeBasisPoints (uint16): 30
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000615400b38307e4fff08b8f494da225b872c77530
Arg [1] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [2] : 000000000000000000000000000000000000000000000000000000000000001e
Deployed Bytecode Sourcemap
371:5119:24:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4368:708:8;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1287:235:6;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;1961:249:24;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1724:108:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5379:109:24;;;;;;;;;;;;;:::i;:::-;;446:46:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2293:101:12;;;;;;;;;;;;;:::i;:::-;;3507:128:8;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2013:216;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5149:148:24;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;421:56;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1638:85:12;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1701:254:24;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;483:28;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;569:48:7;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3252:105;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2216:693:24;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2915:1190;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1503:192;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2543:215:12;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2771:149:8;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4368:708;4694:10;4673:31;;4681:8;4673:31;;;4669:68;;4726:10;4713:24;;;;;;;;;;;:::i;:::-;;;;;;;;4669:68;4873:7;:14;;;4837:32;4854:7;:14;;;;;;;;;;:::i;:::-;4837:16;:32::i;:::-;:50;4833:103;;4905:7;:14;;;;;;;;;;:::i;:::-;4921:7;:14;;;4896:40;;;;;;;;;;;;:::i;:::-;;;;;;;;4833:103;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;1287:235:6:-;1414:20;1436:22;843:1:9;678::8;1474:41:6;;;;1287:235;;:::o;1961:249:24:-;1531:13:12;:11;:13::i;:::-;2055:3:24::1;2037:15;:21;;;2033:86;;;2084:15;2101:17;2067:52;;;;;;;;;;;;:::i;:::-;;;;;;;;2033:86;2146:15;2129:14;;:32;;;;;;;;;;;;;;;;;;2187:15;2176:27;;;;;;;;;;;;1961:249:::0;:::o;1724:108:7:-;1531:13:12;:11;:13::i;:::-;1804:21:7::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;5379:109:24:-;1531:13:12;:11;:13::i;:::-;5441:7:24::1;:5;:7::i;:::-;5433:25;;:48;5459:21;5433:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;5379:109::o:0;446:46:7:-;;;:::o;2293:101:12:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;3507:128:8:-;3596:12;3507:128;;;;:::o;2013:216::-;2175:4;2217;2198:24;;:7;:24;;;2191:31;;2013:216;;;;;;:::o;5149:148:24:-;1531:13:12;:11;:13::i;:::-;5237:53:24::1;5260:12;5274:7;:5;:7::i;:::-;5283:6;5237:22;:53::i;:::-;5149:148:::0;;:::o;421:56::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1638:85:12:-;1684:7;1710:6;;;;;;;;;;;1703:13;;1638:85;:::o;1701:254:24:-;1531:13:12;:11;:13::i;:::-;1834:1:24::1;1789:47;;1797:15;1813:7;;1797:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1789:47;;::::0;1785:86:::1;;1863:7;;1845:26;;;;;;;;;;;;:::i;:::-;;;;;;;;1785:86;1888:15;1904:7;;1888:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;1881:31;;;;;;;;;;;1940:7;;1927:21;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;1701:254:::0;;:::o;483:28::-;;;;;;;;;;;;;:::o;569:48:7:-;;;;;;;;;;;;;;;;;:::o;3252:105::-;1531:13:12;:11;:13::i;:::-;3319:8:7::1;:20;;;3340:9;3319:31;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3252:105:::0;:::o;2216:693:24:-;2403:17;2456:1;2436:22;;:8;:22;;;2432:59;;2467:24;;;;;;;;;;;;;;2432:59;2501:20;2524:15;2540:6;;2524:23;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;2501:46;;2587:1;2561:28;;2569:5;2561:28;;;2557:66;;2616:6;;2598:25;;;;;;;;;;;;:::i;:::-;;;;;;;;2557:66;2635:22;2662:38;2686:5;2693:6;2662:23;:38::i;:::-;2634:66;;;2711:20;2745:8;2755:6;;2763:14;2734:44;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2711:67;;2789:28;2820:47;2827:13;2842:7;2851:8;;2820:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2861:5;2820:6;:47::i;:::-;2789:78;;2884:8;:18;;;2877:25;;;;;;2216:693;;;;;;;;;:::o;2915:1190::-;3129:31;;:::i;:::-;2500:21:22;:19;:21::i;:::-;3196:1:24::1;3176:22;;:8;:22;;::::0;3172:59:::1;;3207:24;;;;;;;;;;;;;;3172:59;3241:20;3264:15;3280:6;;3264:23;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3241:46;;3327:1;3301:28;;3309:5;3301:28;;::::0;3297:66:::1;;3356:6;;3338:25;;;;;;;;;;;;:::i;:::-;;;;;;;;3297:66;3374:25;3427:21:::0;3451:5:::1;:15;;;3475:4;3451:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3427:54;;3495:68;3522:5;3529:10;3549:4;3556:6;3495:26;:68::i;:::-;3577:20;3600:5;:15;;;3624:4;3600:30;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3577:53;;3679:13;3664:12;:28;;;;:::i;:::-;3644:48;;3413:290;;3714:22;3738:11:::0;3753:49:::1;3777:5;3784:17;3753:23;:49::i;:::-;3713:89;;;;3813:20;3847:8;3857:6;;3865:14;3836:44;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;3813:67;;3901:90;3909:13;3924:7;3933:8;;3901:90;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3943:26;;;;;;;;3956:9;3943:26;;;;3967:1;3943:26;;::::0;3979:10:::1;3901:7;:90::i;:::-;3891:100;;4034:10;4006:92;;4020:7;:12;;;4006:92;4046:5;4053:14;4069:8;4079:3;4084:13;4006:92;;;;;;;;;;:::i;:::-;;;;;;;;3162:943;;;;;2542:20:22::0;:18;:20::i;:::-;2915:1190:24;;;;;;;;;:::o;1503:192::-;1531:13:12;:11;:13::i;:::-;1636:8:24::1;1609:15;1625:7;;1609:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:35;;;;;;;;;;;;;;;;;;1679:8;1659:29;;1670:7;;1659:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;1503:192:::0;;;:::o;2543:215:12:-;1531:13;:11;:13::i;:::-;2647:1:::1;2627:22;;:8;:22;;::::0;2623:91:::1;;2700:1;2672:31;;;;;;;;;;;:::i;:::-;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;2771:149:8:-;2853:4;2900:6;:13;;;2876:5;:20;2882:6;:13;;;;;;;;;;:::i;:::-;2876:20;;;;;;;;;;;;;;;;:37;2869:44;;2771:149;;;:::o;2718:196:7:-;2788:7;2807:12;2822:5;:11;2828:4;2822:11;;;;;;;;;;;;;;;;2807:26;;2863:1;2855:10;;2847:4;:18;2843:43;;2881:4;2874:12;;;;;;;;;;;:::i;:::-;;;;;;;;2843:43;2903:4;2896:11;;;2718:196;;;:::o;4442:651:24:-;2500:21:22;:19;:21::i;:::-;4630:16:24::1;4648:20:::0;4670:14:::1;4699:7;;4688:47;;;;;;;:::i;:::-;4629:106;;;;;;4746:20;4769:15;4785:6;4769:23;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;4746:46;;4832:1;4806:28;;4814:5;4806:28;;::::0;4802:66:::1;;4861:6;4843:25;;;;;;;;;;;:::i;:::-;;;;;;;;4802:66;4879:24;4944:5;4923;:14;;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4917:2;:22;;;;:::i;:::-;4907:6;:33;;;;:::i;:::-;4906:43;;;;:::i;:::-;4879:70;;4985:8;4964:55;;4979:4;4964:55;4995:5;5002:16;4964:55;;;;;;;:::i;:::-;;;;;;;;5029:57;5052:5;5059:8;5069:16;5029:22;:57::i;:::-;4619:474;;;;;2542:20:22::0;:18;:20::i;:::-;4442:651:24;;;;;;;:::o;1796:162:12:-;1866:12;:10;:12::i;:::-;1855:23;;:7;:5;:7::i;:::-;:23;;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;;;;;;;;;;:::i;:::-;;;;;;;;1851:101;1796:162::o;2286:134:7:-;2373:5;2359;:11;2365:4;2359:11;;;;;;;;;;;;;;;:19;;;;2393:20;2401:4;2407:5;2393:20;;;;;;;:::i;:::-;;;;;;;;2286:134;;:::o;2912:187:12:-;2985:16;3004:6;;;;;;;;;;;2985:25;;3029:8;3020:6;;:17;;;;;;;;;;;;;;;;;;3083:8;3052:40;;3073:8;3052:40;;;;;;;;;;;;2975:124;2912:187;:::o;1271:160:18:-;1353:71;1373:5;1395;:14;;;1412:2;1416:5;1380:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1353:19;:71::i;:::-;1271:160;;;:::o;4111:325:24:-;4204:22;4228:11;4251:24;4304:5;:14;;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4298:2;:22;;;;:::i;:::-;4288:5;4279:6;:14;;;;:::i;:::-;4278:43;;;;:::i;:::-;4251:70;;4375:5;4357:14;;;;;;;;;;;4338:33;;:16;:33;;;;:::i;:::-;4337:43;;;;:::i;:::-;4331:49;;4426:3;4407:16;:22;;;;:::i;:::-;4390:39;;4241:195;4111:325;;;;;:::o;2038:391:9:-;2205:23;;:::i;:::-;2259:8;:14;;;2291:86;;;;;;;;2307:7;2291:86;;;;;;2316:25;2333:7;2316:16;:25::i;:::-;2291:86;;;;2343:8;2291:86;;;;2353:8;2291:86;;;;2363:13;2291:86;;;;;2403:4;2259:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2240:182;;2038:391;;;;;;:::o;2575:307:22:-;1899:1;2702:7;;:18;2698:86;;2743:30;;;;;;;;;;;;;;2698:86;1899:1;2858:7;:17;;;;2575:307::o;1670:188:18:-;1770:81;1790:5;1812;:18;;;1833:4;1839:2;1843:5;1797:53;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1770:19;:81::i;:::-;1670:188;;;;:::o;3188:766:9:-;3389:31;;:::i;:::-;3554:20;3577:26;3588:4;:14;;;3577:10;:26::i;:::-;3554:49;;3635:1;3617:4;:15;;;:19;3613:53;;;3638:28;3650:4;:15;;;3638:11;:28::i;:::-;3613:53;3755:8;:13;;;3777:12;3809:92;;;;;;;;3825:7;3809:92;;;;;;3834:25;3851:7;3834:16;:25::i;:::-;3809:92;;;;3861:8;3809:92;;;;3871:8;3809:92;;;;3899:1;3881:4;:15;;;:19;3809:92;;;;;3919:14;3755:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3677:270;;;3188:766;;;;;;;:::o;2888:208:22:-;1857:1;3068:7;:21;;;;2888:208::o;656:96:20:-;709:7;735:10;728:17;;656:96;:::o;7738:720:18:-;7818:18;7846:19;7984:4;7981:1;7974:4;7968:11;7961:4;7955;7951:15;7948:1;7941:5;7934;7929:60;8041:7;8031:176;;8085:4;8079:11;8130:16;8127:1;8122:3;8107:40;8176:16;8171:3;8164:29;8031:176;8234:16;8220:30;;8284:1;8278:8;8263:23;;7900:396;8324:1;8310:10;:15;:68;;8377:1;8362:11;:16;;8310:68;;;8358:1;8336:5;8328:26;;;:31;8310:68;8306:146;;;8434:5;8401:40;;;;;;;;;;;:::i;:::-;;;;;;;;8306:146;7808:650;;7738:720;;:::o;4650:191:9:-;4716:17;4762:10;4749:9;:23;4745:62;;4797:9;4781:26;;;;;;;;;;;:::i;:::-;;;;;;;;4745:62;4824:10;4817:17;;4650:191;;;:::o;5218:410::-;5371:15;5389:8;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5371:36;;5440:1;5421:21;;:7;:21;;;5417:54;;5451:20;;;;;;;;;;;;;;5417:54;5545:76;5578:10;5598:8;5609:11;5552:7;5545:32;;;;:76;;;;;;:::i;:::-;5277:351;5218:410;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;7:75:25:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;478:228;548:5;589:2;580:6;575:3;571:16;567:25;564:112;;;595:79;;:::i;:::-;564:112;694:6;685:15;;478:228;;;;:::o;712:77::-;749:7;778:5;767:16;;712:77;;;:::o;795:122::-;868:24;886:5;868:24;:::i;:::-;861:5;858:35;848:63;;907:1;904;897:12;848:63;795:122;:::o;923:139::-;969:5;1007:6;994:20;985:29;;1023:33;1050:5;1023:33;:::i;:::-;923:139;;;;:::o;1068:117::-;1177:1;1174;1167:12;1191:117;1300:1;1297;1290:12;1314:117;1423:1;1420;1413:12;1450:552;1507:8;1517:6;1567:3;1560:4;1552:6;1548:17;1544:27;1534:122;;1575:79;;:::i;:::-;1534:122;1688:6;1675:20;1665:30;;1718:18;1710:6;1707:30;1704:117;;;1740:79;;:::i;:::-;1704:117;1854:4;1846:6;1842:17;1830:29;;1908:3;1900:4;1892:6;1888:17;1878:8;1874:32;1871:41;1868:128;;;1915:79;;:::i;:::-;1868:128;1450:552;;;;;:::o;2008:126::-;2045:7;2085:42;2078:5;2074:54;2063:65;;2008:126;;;:::o;2140:96::-;2177:7;2206:24;2224:5;2206:24;:::i;:::-;2195:35;;2140:96;;;:::o;2242:122::-;2315:24;2333:5;2315:24;:::i;:::-;2308:5;2305:35;2295:63;;2354:1;2351;2344:12;2295:63;2242:122;:::o;2370:139::-;2416:5;2454:6;2441:20;2432:29;;2470:33;2497:5;2470:33;:::i;:::-;2370:139;;;;:::o;2515:1357::-;2656:6;2664;2672;2680;2688;2696;2704;2753:3;2741:9;2732:7;2728:23;2724:33;2721:120;;;2760:79;;:::i;:::-;2721:120;2880:1;2905:77;2974:7;2965:6;2954:9;2950:22;2905:77;:::i;:::-;2895:87;;2851:141;3031:2;3057:53;3102:7;3093:6;3082:9;3078:22;3057:53;:::i;:::-;3047:63;;3002:118;3187:3;3176:9;3172:19;3159:33;3219:18;3211:6;3208:30;3205:117;;;3241:79;;:::i;:::-;3205:117;3354:64;3410:7;3401:6;3390:9;3386:22;3354:64;:::i;:::-;3336:82;;;;3130:298;3467:3;3494:53;3539:7;3530:6;3519:9;3515:22;3494:53;:::i;:::-;3484:63;;3438:119;3624:3;3613:9;3609:19;3596:33;3656:18;3648:6;3645:30;3642:117;;;3678:79;;:::i;:::-;3642:117;3791:64;3847:7;3838:6;3827:9;3823:22;3791:64;:::i;:::-;3773:82;;;;3567:298;2515:1357;;;;;;;;;;:::o;3878:101::-;3914:7;3954:18;3947:5;3943:30;3932:41;;3878:101;;;:::o;3985:115::-;4070:23;4087:5;4070:23;:::i;:::-;4065:3;4058:36;3985:115;;:::o;4106:324::-;4223:4;4261:2;4250:9;4246:18;4238:26;;4274:69;4340:1;4329:9;4325:17;4316:6;4274:69;:::i;:::-;4353:70;4419:2;4408:9;4404:18;4395:6;4353:70;:::i;:::-;4106:324;;;;;:::o;4436:89::-;4472:7;4512:6;4505:5;4501:18;4490:29;;4436:89;;;:::o;4531:120::-;4603:23;4620:5;4603:23;:::i;:::-;4596:5;4593:34;4583:62;;4641:1;4638;4631:12;4583:62;4531:120;:::o;4657:137::-;4702:5;4740:6;4727:20;4718:29;;4756:32;4782:5;4756:32;:::i;:::-;4657:137;;;;:::o;4800:327::-;4858:6;4907:2;4895:9;4886:7;4882:23;4878:32;4875:119;;;4913:79;;:::i;:::-;4875:119;5033:1;5058:52;5102:7;5093:6;5082:9;5078:22;5058:52;:::i;:::-;5048:62;;5004:116;4800:327;;;;:::o;5133:93::-;5169:7;5209:10;5202:5;5198:22;5187:33;;5133:93;;;:::o;5232:120::-;5304:23;5321:5;5304:23;:::i;:::-;5297:5;5294:34;5284:62;;5342:1;5339;5332:12;5284:62;5232:120;:::o;5358:137::-;5403:5;5441:6;5428:20;5419:29;;5457:32;5483:5;5457:32;:::i;:::-;5358:137;;;;:::o;5501:472::-;5568:6;5576;5625:2;5613:9;5604:7;5600:23;5596:32;5593:119;;;5631:79;;:::i;:::-;5593:119;5751:1;5776:52;5820:7;5811:6;5800:9;5796:22;5776:52;:::i;:::-;5766:62;;5722:116;5877:2;5903:53;5948:7;5939:6;5928:9;5924:22;5903:53;:::i;:::-;5893:63;;5848:118;5501:472;;;;;:::o;5979:60::-;6007:3;6028:5;6021:12;;5979:60;;;:::o;6045:142::-;6095:9;6128:53;6146:34;6155:24;6173:5;6155:24;:::i;:::-;6146:34;:::i;:::-;6128:53;:::i;:::-;6115:66;;6045:142;;;:::o;6193:126::-;6243:9;6276:37;6307:5;6276:37;:::i;:::-;6263:50;;6193:126;;;:::o;6325:154::-;6403:9;6436:37;6467:5;6436:37;:::i;:::-;6423:50;;6325:154;;;:::o;6485:187::-;6600:65;6659:5;6600:65;:::i;:::-;6595:3;6588:78;6485:187;;:::o;6678:278::-;6799:4;6837:2;6826:9;6822:18;6814:26;;6850:99;6946:1;6935:9;6931:17;6922:6;6850:99;:::i;:::-;6678:278;;;;:::o;6962:218::-;7053:4;7091:2;7080:9;7076:18;7068:26;;7104:69;7170:1;7159:9;7155:17;7146:6;7104:69;:::i;:::-;6962:218;;;;:::o;7186:867::-;7298:6;7306;7314;7322;7371:3;7359:9;7350:7;7346:23;7342:33;7339:120;;;7378:79;;:::i;:::-;7339:120;7498:1;7523:77;7592:7;7583:6;7572:9;7568:22;7523:77;:::i;:::-;7513:87;;7469:141;7677:2;7666:9;7662:18;7649:32;7708:18;7700:6;7697:30;7694:117;;;7730:79;;:::i;:::-;7694:117;7843:64;7899:7;7890:6;7879:9;7875:22;7843:64;:::i;:::-;7825:82;;;;7620:297;7956:3;7983:53;8028:7;8019:6;8008:9;8004:22;7983:53;:::i;:::-;7973:63;;7927:119;7186:867;;;;;;;:::o;8059:90::-;8093:7;8136:5;8129:13;8122:21;8111:32;;8059:90;;;:::o;8155:109::-;8236:21;8251:5;8236:21;:::i;:::-;8231:3;8224:34;8155:109;;:::o;8270:210::-;8357:4;8395:2;8384:9;8380:18;8372:26;;8408:65;8470:1;8459:9;8455:17;8446:6;8408:65;:::i;:::-;8270:210;;;;:::o;8486:111::-;8538:7;8567:24;8585:5;8567:24;:::i;:::-;8556:35;;8486:111;;;:::o;8603:152::-;8691:39;8724:5;8691:39;:::i;:::-;8684:5;8681:50;8671:78;;8745:1;8742;8735:12;8671:78;8603:152;:::o;8761:169::-;8822:5;8860:6;8847:20;8838:29;;8876:48;8918:5;8876:48;:::i;:::-;8761:169;;;;:::o;8936:77::-;8973:7;9002:5;8991:16;;8936:77;;;:::o;9019:122::-;9092:24;9110:5;9092:24;:::i;:::-;9085:5;9082:35;9072:63;;9131:1;9128;9121:12;9072:63;9019:122;:::o;9147:139::-;9193:5;9231:6;9218:20;9209:29;;9247:33;9274:5;9247:33;:::i;:::-;9147:139;;;;:::o;9292:504::-;9375:6;9383;9432:2;9420:9;9411:7;9407:23;9403:32;9400:119;;;9438:79;;:::i;:::-;9400:119;9558:1;9583:68;9643:7;9634:6;9623:9;9619:22;9583:68;:::i;:::-;9573:78;;9529:132;9700:2;9726:53;9771:7;9762:6;9751:9;9747:22;9726:53;:::i;:::-;9716:63;;9671:118;9292:504;;;;;:::o;9802:117::-;9911:1;9908;9901:12;9925:102;9966:6;10017:2;10013:7;10008:2;10001:5;9997:14;9993:28;9983:38;;9925:102;;;:::o;10033:180::-;10081:77;10078:1;10071:88;10178:4;10175:1;10168:15;10202:4;10199:1;10192:15;10219:281;10302:27;10324:4;10302:27;:::i;:::-;10294:6;10290:40;10432:6;10420:10;10417:22;10396:18;10384:10;10381:34;10378:62;10375:88;;;10443:18;;:::i;:::-;10375:88;10483:10;10479:2;10472:22;10262:238;10219:281;;:::o;10506:129::-;10540:6;10567:20;;:::i;:::-;10557:30;;10596:33;10624:4;10616:6;10596:33;:::i;:::-;10506:129;;;:::o;10641:308::-;10703:4;10793:18;10785:6;10782:30;10779:56;;;10815:18;;:::i;:::-;10779:56;10853:29;10875:6;10853:29;:::i;:::-;10845:37;;10937:4;10931;10927:15;10919:23;;10641:308;;;:::o;10955:148::-;11053:6;11048:3;11043;11030:30;11094:1;11085:6;11080:3;11076:16;11069:27;10955:148;;;:::o;11109:425::-;11187:5;11212:66;11228:49;11270:6;11228:49;:::i;:::-;11212:66;:::i;:::-;11203:75;;11301:6;11294:5;11287:21;11339:4;11332:5;11328:16;11377:3;11368:6;11363:3;11359:16;11356:25;11353:112;;;11384:79;;:::i;:::-;11353:112;11474:54;11521:6;11516:3;11511;11474:54;:::i;:::-;11193:341;11109:425;;;;;:::o;11554:340::-;11610:5;11659:3;11652:4;11644:6;11640:17;11636:27;11626:122;;11667:79;;:::i;:::-;11626:122;11784:6;11771:20;11809:79;11884:3;11876:6;11869:4;11861:6;11857:17;11809:79;:::i;:::-;11800:88;;11616:278;11554:340;;;;:::o;11900:509::-;11969:6;12018:2;12006:9;11997:7;11993:23;11989:32;11986:119;;;12024:79;;:::i;:::-;11986:119;12172:1;12161:9;12157:17;12144:31;12202:18;12194:6;12191:30;12188:117;;;12224:79;;:::i;:::-;12188:117;12329:63;12384:7;12375:6;12364:9;12360:22;12329:63;:::i;:::-;12319:73;;12115:287;11900:509;;;;:::o;12415:149::-;12488:9;12521:37;12552:5;12521:37;:::i;:::-;12508:50;;12415:149;;;:::o;12570:177::-;12680:60;12734:5;12680:60;:::i;:::-;12675:3;12668:73;12570:177;;:::o;12753:268::-;12869:4;12907:2;12896:9;12892:18;12884:26;;12920:94;13011:1;13000:9;12996:17;12987:6;12920:94;:::i;:::-;12753:268;;;;:::o;13027:118::-;13114:24;13132:5;13114:24;:::i;:::-;13109:3;13102:37;13027:118;;:::o;13151:222::-;13244:4;13282:2;13271:9;13267:18;13259:26;;13295:71;13363:1;13352:9;13348:17;13339:6;13295:71;:::i;:::-;13151:222;;;;:::o;13393:553::-;13451:8;13461:6;13511:3;13504:4;13496:6;13492:17;13488:27;13478:122;;13519:79;;:::i;:::-;13478:122;13632:6;13619:20;13609:30;;13662:18;13654:6;13651:30;13648:117;;;13684:79;;:::i;:::-;13648:117;13798:4;13790:6;13786:17;13774:29;;13852:3;13844:4;13836:6;13832:17;13822:8;13818:32;13815:41;13812:128;;;13859:79;;:::i;:::-;13812:128;13393:553;;;;;:::o;13952:529::-;14023:6;14031;14080:2;14068:9;14059:7;14055:23;14051:32;14048:119;;;14086:79;;:::i;:::-;14048:119;14234:1;14223:9;14219:17;14206:31;14264:18;14256:6;14253:30;14250:117;;;14286:79;;:::i;:::-;14250:117;14399:65;14456:7;14447:6;14436:9;14432:22;14399:65;:::i;:::-;14381:83;;;;14177:297;13952:529;;;;;:::o;14487:115::-;14572:23;14589:5;14572:23;:::i;:::-;14567:3;14560:36;14487:115;;:::o;14608:218::-;14699:4;14737:2;14726:9;14722:18;14714:26;;14750:69;14816:1;14805:9;14801:17;14792:6;14750:69;:::i;:::-;14608:218;;;;:::o;14832:327::-;14890:6;14939:2;14927:9;14918:7;14914:23;14910:32;14907:119;;;14945:79;;:::i;:::-;14907:119;15065:1;15090:52;15134:7;15125:6;15114:9;15110:22;15090:52;:::i;:::-;15080:62;;15036:116;14832:327;;;;:::o;15165:118::-;15252:24;15270:5;15252:24;:::i;:::-;15247:3;15240:37;15165:118;;:::o;15289:222::-;15382:4;15420:2;15409:9;15405:18;15397:26;;15433:71;15501:1;15490:9;15486:17;15477:6;15433:71;:::i;:::-;15289:222;;;;:::o;15517:329::-;15576:6;15625:2;15613:9;15604:7;15600:23;15596:32;15593:119;;;15631:79;;:::i;:::-;15593:119;15751:1;15776:53;15821:7;15812:6;15801:9;15797:22;15776:53;:::i;:::-;15766:63;;15722:117;15517:329;;;;:::o;15852:1307::-;15969:6;15977;15985;15993;16001;16009;16017;16066:3;16054:9;16045:7;16041:23;16037:33;16034:120;;;16073:79;;:::i;:::-;16034:120;16221:1;16210:9;16206:17;16193:31;16251:18;16243:6;16240:30;16237:117;;;16273:79;;:::i;:::-;16237:117;16386:65;16443:7;16434:6;16423:9;16419:22;16386:65;:::i;:::-;16368:83;;;;16164:297;16500:2;16526:53;16571:7;16562:6;16551:9;16547:22;16526:53;:::i;:::-;16516:63;;16471:118;16628:2;16654:53;16699:7;16690:6;16679:9;16675:22;16654:53;:::i;:::-;16644:63;;16599:118;16756:2;16782:52;16826:7;16817:6;16806:9;16802:22;16782:52;:::i;:::-;16772:62;;16727:117;16911:3;16900:9;16896:19;16883:33;16943:18;16935:6;16932:30;16929:117;;;16965:79;;:::i;:::-;16929:117;17078:64;17134:7;17125:6;17114:9;17110:22;17078:64;:::i;:::-;17060:82;;;;16854:298;15852:1307;;;;;;;;;;:::o;17165:118::-;17252:24;17270:5;17252:24;:::i;:::-;17247:3;17240:37;17165:118;;:::o;17289:222::-;17382:4;17420:2;17409:9;17405:18;17397:26;;17433:71;17501:1;17490:9;17486:17;17477:6;17433:71;:::i;:::-;17289:222;;;;:::o;17517:108::-;17594:24;17612:5;17594:24;:::i;:::-;17589:3;17582:37;17517:108;;:::o;17631:105::-;17706:23;17723:5;17706:23;:::i;:::-;17701:3;17694:36;17631:105;;:::o;17742:108::-;17819:24;17837:5;17819:24;:::i;:::-;17814:3;17807:37;17742:108;;:::o;17906:514::-;18049:4;18044:3;18040:14;18141:4;18134:5;18130:16;18124:23;18160:63;18217:4;18212:3;18208:14;18194:12;18160:63;:::i;:::-;18064:169;18321:4;18314:5;18310:16;18304:23;18340:63;18397:4;18392:3;18388:14;18374:12;18340:63;:::i;:::-;18243:170;18018:402;17906:514;;:::o;18484:749::-;18645:4;18640:3;18636:14;18732:4;18725:5;18721:16;18715:23;18751:63;18808:4;18803:3;18799:14;18785:12;18751:63;:::i;:::-;18660:164;18907:4;18900:5;18896:16;18890:23;18926:61;18981:4;18976:3;18972:14;18958:12;18926:61;:::i;:::-;18834:163;19078:4;19071:5;19067:16;19061:23;19097:119;19210:4;19205:3;19201:14;19187:12;19097:119;:::i;:::-;19007:219;18614:619;18484:749;;:::o;19239:351::-;19396:4;19434:3;19423:9;19419:19;19411:27;;19448:135;19580:1;19569:9;19565:17;19556:6;19448:135;:::i;:::-;19239:351;;;;:::o;19596:119::-;19656:7;19685:24;19703:5;19685:24;:::i;:::-;19674:35;;19596:119;;;:::o;19721:168::-;19817:47;19858:5;19817:47;:::i;:::-;19810:5;19807:58;19797:86;;19879:1;19876;19869:12;19797:86;19721:168;:::o;19895:185::-;19964:5;20002:6;19989:20;19980:29;;20018:56;20068:5;20018:56;:::i;:::-;19895:185;;;;:::o;20086:720::-;20189:6;20197;20205;20254:2;20242:9;20233:7;20229:23;20225:32;20222:119;;;20260:79;;:::i;:::-;20222:119;20408:1;20397:9;20393:17;20380:31;20438:18;20430:6;20427:30;20424:117;;;20460:79;;:::i;:::-;20424:117;20573:65;20630:7;20621:6;20610:9;20606:22;20573:65;:::i;:::-;20555:83;;;;20351:297;20687:2;20713:76;20781:7;20772:6;20761:9;20757:22;20713:76;:::i;:::-;20703:86;;20658:141;20086:720;;;;;:::o;20812:377::-;20895:6;20944:2;20932:9;20923:7;20919:23;20915:32;20912:119;;;20950:79;;:::i;:::-;20912:119;21070:1;21095:77;21164:7;21155:6;21144:9;21140:22;21095:77;:::i;:::-;21085:87;;21041:141;20812:377;;;;:::o;21195:115::-;21280:23;21297:5;21280:23;:::i;:::-;21275:3;21268:36;21195:115;;:::o;21316:328::-;21435:4;21473:2;21462:9;21458:18;21450:26;;21486:69;21552:1;21541:9;21537:17;21528:6;21486:69;:::i;:::-;21565:72;21633:2;21622:9;21618:18;21609:6;21565:72;:::i;:::-;21316:328;;;;;:::o;21650:324::-;21767:4;21805:2;21794:9;21790:18;21782:26;;21818:69;21884:1;21873:9;21869:17;21860:6;21818:69;:::i;:::-;21897:70;21963:2;21952:9;21948:18;21939:6;21897:70;:::i;:::-;21650:324;;;;;:::o;21980:148::-;22082:11;22119:3;22104:18;;21980:148;;;;:::o;22158:330::-;22274:3;22295:89;22377:6;22372:3;22295:89;:::i;:::-;22288:96;;22394:56;22443:6;22438:3;22431:5;22394:56;:::i;:::-;22475:6;22470:3;22466:16;22459:23;;22158:330;;;;;:::o;22494:295::-;22636:3;22658:105;22759:3;22750:6;22742;22658:105;:::i;:::-;22651:112;;22780:3;22773:10;;22494:295;;;;;:::o;22795:169::-;22879:11;22913:6;22908:3;22901:19;22953:4;22948:3;22944:14;22929:29;;22795:169;;;;:::o;22994:317::-;23092:3;23113:71;23177:6;23172:3;23113:71;:::i;:::-;23106:78;;23194:56;23243:6;23238:3;23231:5;23194:56;:::i;:::-;23275:29;23297:6;23275:29;:::i;:::-;23270:3;23266:39;23259:46;;22994:317;;;;;:::o;23317:333::-;23440:4;23478:2;23467:9;23463:18;23455:26;;23527:9;23521:4;23517:20;23513:1;23502:9;23498:17;23491:47;23555:88;23638:4;23629:6;23621;23555:88;:::i;:::-;23547:96;;23317:333;;;;;:::o;23656:553::-;23835:4;23873:2;23862:9;23858:18;23850:26;;23886:71;23954:1;23943:9;23939:17;23930:6;23886:71;:::i;:::-;24004:9;23998:4;23994:20;23989:2;23978:9;23974:18;23967:48;24032:88;24115:4;24106:6;24098;24032:88;:::i;:::-;24024:96;;24130:72;24198:2;24187:9;24183:18;24174:6;24130:72;:::i;:::-;23656:553;;;;;;;:::o;24215:143::-;24272:5;24303:6;24297:13;24288:22;;24319:33;24346:5;24319:33;:::i;:::-;24215:143;;;;:::o;24364:351::-;24434:6;24483:2;24471:9;24462:7;24458:23;24454:32;24451:119;;;24489:79;;:::i;:::-;24451:119;24609:1;24634:64;24690:7;24681:6;24670:9;24666:22;24634:64;:::i;:::-;24624:74;;24580:128;24364:351;;;;:::o;24721:180::-;24769:77;24766:1;24759:88;24866:4;24863:1;24856:15;24890:4;24887:1;24880:15;24907:194;24947:4;24967:20;24985:1;24967:20;:::i;:::-;24962:25;;25001:20;25019:1;25001:20;:::i;:::-;24996:25;;25045:1;25042;25038:9;25030:17;;25069:1;25063:4;25060:11;25057:37;;;25074:18;;:::i;:::-;25057:37;24907:194;;;;:::o;25107:706::-;25333:4;25371:3;25360:9;25356:19;25348:27;;25385:94;25476:1;25465:9;25461:17;25452:6;25385:94;:::i;:::-;25489:72;25557:2;25546:9;25542:18;25533:6;25489:72;:::i;:::-;25571;25639:2;25628:9;25624:18;25615:6;25571:72;:::i;:::-;25653;25721:2;25710:9;25706:18;25697:6;25653:72;:::i;:::-;25735:71;25801:3;25790:9;25786:19;25777:6;25735:71;:::i;:::-;25107:706;;;;;;;;:::o;25819:218::-;25910:4;25948:2;25937:9;25933:18;25925:26;;25961:69;26027:1;26016:9;26012:17;26003:6;25961:69;:::i;:::-;25819:218;;;;:::o;26043:104::-;26088:7;26117:24;26135:5;26117:24;:::i;:::-;26106:35;;26043:104;;;:::o;26153:138::-;26234:32;26260:5;26234:32;:::i;:::-;26227:5;26224:43;26214:71;;26281:1;26278;26271:12;26214:71;26153:138;:::o;26297:155::-;26351:5;26389:6;26376:20;26367:29;;26405:41;26440:5;26405:41;:::i;:::-;26297:155;;;;:::o;26458:815::-;26553:6;26561;26569;26618:2;26606:9;26597:7;26593:23;26589:32;26586:119;;;26624:79;;:::i;:::-;26586:119;26744:1;26769:61;26822:7;26813:6;26802:9;26798:22;26769:61;:::i;:::-;26759:71;;26715:125;26907:2;26896:9;26892:18;26879:32;26938:18;26930:6;26927:30;26924:117;;;26960:79;;:::i;:::-;26924:117;27065:63;27120:7;27111:6;27100:9;27096:22;27065:63;:::i;:::-;27055:73;;26850:288;27177:2;27203:53;27248:7;27239:6;27228:9;27224:22;27203:53;:::i;:::-;27193:63;;27148:118;26458:815;;;;;:::o;27279:99::-;27331:6;27365:5;27359:12;27349:22;;27279:99;;;:::o;27384:139::-;27473:6;27468:3;27463;27457:23;27514:1;27505:6;27500:3;27496:16;27489:27;27384:139;;;:::o;27529:390::-;27635:3;27663:39;27696:5;27663:39;:::i;:::-;27718:89;27800:6;27795:3;27718:89;:::i;:::-;27711:96;;27816:65;27874:6;27869:3;27862:4;27855:5;27851:16;27816:65;:::i;:::-;27906:6;27901:3;27897:16;27890:23;;27639:280;27529:390;;;;:::o;27925:275::-;28057:3;28079:95;28170:3;28161:6;28079:95;:::i;:::-;28072:102;;28191:3;28184:10;;27925:275;;;;:::o;28206:377::-;28294:3;28322:39;28355:5;28322:39;:::i;:::-;28377:71;28441:6;28436:3;28377:71;:::i;:::-;28370:78;;28457:65;28515:6;28510:3;28503:4;28496:5;28492:16;28457:65;:::i;:::-;28547:29;28569:6;28547:29;:::i;:::-;28542:3;28538:39;28531:46;;28298:285;28206:377;;;;:::o;28589:313::-;28702:4;28740:2;28729:9;28725:18;28717:26;;28789:9;28783:4;28779:20;28775:1;28764:9;28760:17;28753:47;28817:78;28890:4;28881:6;28817:78;:::i;:::-;28809:86;;28589:313;;;;:::o;28908:86::-;28943:7;28983:4;28976:5;28972:16;28961:27;;28908:86;;;:::o;29000:118::-;29071:22;29087:5;29071:22;:::i;:::-;29064:5;29061:33;29051:61;;29108:1;29105;29098:12;29051:61;29000:118;:::o;29124:139::-;29179:5;29210:6;29204:13;29195:22;;29226:31;29251:5;29226:31;:::i;:::-;29124:139;;;;:::o;29269:347::-;29337:6;29386:2;29374:9;29365:7;29361:23;29357:32;29354:119;;;29392:79;;:::i;:::-;29354:119;29512:1;29537:62;29591:7;29582:6;29571:9;29567:22;29537:62;:::i;:::-;29527:72;;29483:126;29269:347;;;;:::o;29622:102::-;29664:8;29711:5;29708:1;29704:13;29683:34;;29622:102;;;:::o;29730:848::-;29791:5;29798:4;29822:6;29813:15;;29846:5;29837:14;;29860:712;29881:1;29871:8;29868:15;29860:712;;;29976:4;29971:3;29967:14;29961:4;29958:24;29955:50;;;29985:18;;:::i;:::-;29955:50;30035:1;30025:8;30021:16;30018:451;;;30450:4;30443:5;30439:16;30430:25;;30018:451;30500:4;30494;30490:15;30482:23;;30530:32;30553:8;30530:32;:::i;:::-;30518:44;;29860:712;;;29730:848;;;;;;;:::o;30584:1073::-;30638:5;30829:8;30819:40;;30850:1;30841:10;;30852:5;;30819:40;30878:4;30868:36;;30895:1;30886:10;;30897:5;;30868:36;30964:4;31012:1;31007:27;;;;31048:1;31043:191;;;;30957:277;;31007:27;31025:1;31016:10;;31027:5;;;31043:191;31088:3;31078:8;31075:17;31072:43;;;31095:18;;:::i;:::-;31072:43;31144:8;31141:1;31137:16;31128:25;;31179:3;31172:5;31169:14;31166:40;;;31186:18;;:::i;:::-;31166:40;31219:5;;;30957:277;;31343:2;31333:8;31330:16;31324:3;31318:4;31315:13;31311:36;31293:2;31283:8;31280:16;31275:2;31269:4;31266:12;31262:35;31246:111;31243:246;;;31399:8;31393:4;31389:19;31380:28;;31434:3;31427:5;31424:14;31421:40;;;31441:18;;:::i;:::-;31421:40;31474:5;;31243:246;31514:42;31552:3;31542:8;31536:4;31533:1;31514:42;:::i;:::-;31499:57;;;;31588:4;31583:3;31579:14;31572:5;31569:25;31566:51;;;31597:18;;:::i;:::-;31566:51;31646:4;31639:5;31635:16;31626:25;;30584:1073;;;;;;:::o;31663:281::-;31721:5;31745:23;31763:4;31745:23;:::i;:::-;31737:31;;31789:25;31805:8;31789:25;:::i;:::-;31777:37;;31833:104;31870:66;31860:8;31854:4;31833:104;:::i;:::-;31824:113;;31663:281;;;;:::o;31950:410::-;31990:7;32013:20;32031:1;32013:20;:::i;:::-;32008:25;;32047:20;32065:1;32047:20;:::i;:::-;32042:25;;32102:1;32099;32095:9;32124:30;32142:11;32124:30;:::i;:::-;32113:41;;32303:1;32294:7;32290:15;32287:1;32284:22;32264:1;32257:9;32237:83;32214:139;;32333:18;;:::i;:::-;32214:139;31998:362;31950:410;;;;:::o;32366:180::-;32414:77;32411:1;32404:88;32511:4;32508:1;32501:15;32535:4;32532:1;32525:15;32552:185;32592:1;32609:20;32627:1;32609:20;:::i;:::-;32604:25;;32643:20;32661:1;32643:20;:::i;:::-;32638:25;;32682:1;32672:35;;32687:18;;:::i;:::-;32672:35;32729:1;32726;32722:9;32717:14;;32552:185;;;;:::o;32743:378::-;32887:4;32925:2;32914:9;32910:18;32902:26;;32938:94;33029:1;33018:9;33014:17;33005:6;32938:94;:::i;:::-;33042:72;33110:2;33099:9;33095:18;33086:6;33042:72;:::i;:::-;32743:378;;;;;:::o;33127:332::-;33248:4;33286:2;33275:9;33271:18;33263:26;;33299:71;33367:1;33356:9;33352:17;33343:6;33299:71;:::i;:::-;33380:72;33448:2;33437:9;33433:18;33424:6;33380:72;:::i;:::-;33127:332;;;;;:::o;33465:105::-;33540:23;33557:5;33540:23;:::i;:::-;33535:3;33528:36;33465:105;;:::o;33576:98::-;33627:6;33661:5;33655:12;33645:22;;33576:98;;;:::o;33680:158::-;33753:11;33787:6;33782:3;33775:19;33827:4;33822:3;33818:14;33803:29;;33680:158;;;;:::o;33844:353::-;33920:3;33948:38;33980:5;33948:38;:::i;:::-;34002:60;34055:6;34050:3;34002:60;:::i;:::-;33995:67;;34071:65;34129:6;34124:3;34117:4;34110:5;34106:16;34071:65;:::i;:::-;34161:29;34183:6;34161:29;:::i;:::-;34156:3;34152:39;34145:46;;33924:273;33844:353;;;;:::o;34203:99::-;34274:21;34289:5;34274:21;:::i;:::-;34269:3;34262:34;34203:99;;:::o;34364:1219::-;34495:3;34531:4;34526:3;34522:14;34620:4;34613:5;34609:16;34603:23;34639:61;34694:4;34689:3;34685:14;34671:12;34639:61;:::i;:::-;34546:164;34796:4;34789:5;34785:16;34779:23;34815:63;34872:4;34867:3;34863:14;34849:12;34815:63;:::i;:::-;34720:168;34973:4;34966:5;34962:16;34956:23;35026:3;35020:4;35016:14;35009:4;35004:3;35000:14;34993:38;35052:71;35118:4;35104:12;35052:71;:::i;:::-;35044:79;;34898:236;35219:4;35212:5;35208:16;35202:23;35272:3;35266:4;35262:14;35255:4;35250:3;35246:14;35239:38;35298:71;35364:4;35350:12;35298:71;:::i;:::-;35290:79;;35144:236;35470:4;35463:5;35459:16;35453:23;35489:57;35540:4;35535:3;35531:14;35517:12;35489:57;:::i;:::-;35390:166;35573:4;35566:11;;34500:1083;34364:1219;;;;:::o;35589:507::-;35772:4;35810:2;35799:9;35795:18;35787:26;;35859:9;35853:4;35849:20;35845:1;35834:9;35830:17;35823:47;35887:120;36002:4;35993:6;35887:120;:::i;:::-;35879:128;;36017:72;36085:2;36074:9;36070:18;36061:6;36017:72;:::i;:::-;35589:507;;;;;:::o;36102:117::-;36211:1;36208;36201:12;36375:621;36463:5;36507:4;36495:9;36490:3;36486:19;36482:30;36479:117;;;36515:79;;:::i;:::-;36479:117;36614:21;36630:4;36614:21;:::i;:::-;36605:30;;36699:1;36739:60;36795:3;36786:6;36775:9;36771:22;36739:60;:::i;:::-;36732:4;36725:5;36721:16;36714:86;36645:166;36876:2;36917:60;36973:3;36964:6;36953:9;36949:22;36917:60;:::i;:::-;36910:4;36903:5;36899:16;36892:86;36821:168;36375:621;;;;:::o;37002:407::-;37100:6;37149:2;37137:9;37128:7;37124:23;37120:32;37117:119;;;37155:79;;:::i;:::-;37117:119;37275:1;37300:92;37384:7;37375:6;37364:9;37360:22;37300:92;:::i;:::-;37290:102;;37246:156;37002:407;;;;:::o;37415:442::-;37564:4;37602:2;37591:9;37587:18;37579:26;;37615:71;37683:1;37672:9;37668:17;37659:6;37615:71;:::i;:::-;37696:72;37764:2;37753:9;37749:18;37740:6;37696:72;:::i;:::-;37778;37846:2;37835:9;37831:18;37822:6;37778:72;:::i;:::-;37415:442;;;;;;:::o;37863:143::-;37920:5;37951:6;37945:13;37936:22;;37967:33;37994:5;37967:33;:::i;:::-;37863:143;;;;:::o;38012:120::-;38084:23;38101:5;38084:23;:::i;:::-;38077:5;38074:34;38064:62;;38122:1;38119;38112:12;38064:62;38012:120;:::o;38138:141::-;38194:5;38225:6;38219:13;38210:22;;38241:32;38267:5;38241:32;:::i;:::-;38138:141;;;;:::o;38316:813::-;38408:5;38452:4;38440:9;38435:3;38431:19;38427:30;38424:117;;;38460:79;;:::i;:::-;38424:117;38559:21;38575:4;38559:21;:::i;:::-;38550:30;;38639:1;38679:60;38735:3;38726:6;38715:9;38711:22;38679:60;:::i;:::-;38672:4;38665:5;38661:16;38654:86;38590:161;38811:2;38852:59;38907:3;38898:6;38887:9;38883:22;38852:59;:::i;:::-;38845:4;38838:5;38834:16;38827:85;38761:162;38981:2;39022:88;39106:3;39097:6;39086:9;39082:22;39022:88;:::i;:::-;39015:4;39008:5;39004:16;38997:114;38933:189;38316:813;;;;:::o;39135:416::-;39237:6;39286:3;39274:9;39265:7;39261:23;39257:33;39254:120;;;39293:79;;:::i;:::-;39254:120;39413:1;39438:96;39526:7;39517:6;39506:9;39502:22;39438:96;:::i;:::-;39428:106;;39384:160;39135:416;;;;:::o;39557:143::-;39614:5;39645:6;39639:13;39630:22;;39661:33;39688:5;39661:33;:::i;:::-;39557:143;;;;:::o;39706:351::-;39776:6;39825:2;39813:9;39804:7;39800:23;39796:32;39793:119;;;39831:79;;:::i;:::-;39793:119;39951:1;39976:64;40032:7;40023:6;40012:9;40008:22;39976:64;:::i;:::-;39966:74;;39922:128;39706:351;;;;:::o
Swarm Source
ipfs://65f854c363cf9ab14e4c280709db47ab5702824f21efdc503d67062adcf72169
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BASE | 100.00% | $1 | 0.5184 | $0.5184 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.