Overview [ERC-20]
Price
$2.89 @ 0.000937 Eth (-9.98%)
Fully Diluted Market Cap
Max Total Supply:
6,178,875.641627 MAVIA
Holders:
2,118 ( 0.567%)
Transfers:
-
Contract:
Decimals:
18
Official Site:
[ Download CSV Export ]
[ Download CSV Export ]
OVERVIEW
Heroes of Mavia is a mobile multiplayer Web3 strategy game where players use their base and army to battle other players. Players are able to earn in-game “Legendary Items” through our “Mass Ownership” model, powered by Ruby - our flagship premium earn-only currency.Market
Volume (24H) | : | $50,719,902.00 |
Market Capitalization | : | $86,328,379.00 |
Circulating Supply | : | 30,000,000.00 MAVIA |
Market Data Source: Coinmarketcap |
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MaviaOFT
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol"; // @dev Import the 'Origin' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppReceiver, Origin } from "./OAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OApp * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality. */ abstract contract OApp is OAppSender, OAppReceiver { /** * @dev Constructor to initialize the OApp with the provided endpoint and owner. * @param _endpoint The address of the LOCAL LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol implementation. * @return receiverVersion The version of the OAppReceiver.sol implementation. */ function oAppVersion() public pure virtual override(OAppSender, OAppReceiver) returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, RECEIVER_VERSION); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { 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 { 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 = 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 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 Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() public view virtual returns (address sender) { return 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 pragma solidity ^0.8.20; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title IOAppCore */ interface IOAppCore { // Custom error messages error OnlyPeer(uint32 eid, bytes32 sender); error NoPeer(uint32 eid); error InvalidEndpointCall(); error InvalidDelegate(); // Event emitted when a peer (OApp) is set for a corresponding endpoint event PeerSet(uint32 eid, bytes32 peer); /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. */ function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion); /** * @notice Retrieves the LayerZero endpoint associated with the OApp. * @return iEndpoint The LayerZero endpoint as an interface. */ function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint); /** * @notice Retrieves the peer (OApp) associated with a corresponding endpoint. * @param _eid The endpoint ID. * @return peer The peer address (OApp instance) associated with the corresponding endpoint. */ function peers(uint32 _eid) external view returns (bytes32 peer); /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. */ function setPeer(uint32 _eid, bytes32 _peer) external; /** * @notice Sets the delegate address for the OApp Core. * @param _delegate The address of the delegate to be set. */ function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title IOAppMsgInspector * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents. */ interface IOAppMsgInspector { // Custom error message for inspection failure error InspectionFailed(bytes message, bytes options); /** * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid. * @param _message The message payload to be inspected. * @param _options Additional options or parameters for inspection. * @return valid A boolean indicating whether the inspection passed (true) or failed (false). * * @dev Optionally done as a revert, OR use the boolean provided to handle the failure. */ function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Struct representing enforced option parameters. */ struct EnforcedOptionParam { uint32 eid; // Endpoint ID uint16 msgType; // Message Type bytes options; // Additional options } /** * @title IOAppOptionsType3 * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options. */ interface IOAppOptionsType3 { // Custom error message for invalid options error InvalidOptions(bytes options); // Event emitted when enforced options are set event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions); /** * @notice Sets enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external; /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OApp message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) external view returns (bytes memory options); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; interface IOAppReceiver is ILayerZeroReceiver { /** * @notice Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() external view returns (address sender); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol"; /** * @title OAppOptionsType3 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options. */ abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable { uint16 internal constant OPTION_TYPE_3 = 3; // @dev The "msgType" should be defined in the child contract. mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions; /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner { for (uint256 i = 0; i < _enforcedOptions.length; i++) { // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining. _assertOptionsType3(_enforcedOptions[i].options); enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options; } emit EnforcedOptionSet(_enforcedOptions); } /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OAPP message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. * * @dev If there is an enforced lzReceive option: * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether} * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function. * @dev This presence of duplicated options is handled off-chain in the verifier/executor. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) public view virtual returns (bytes memory) { bytes memory enforced = enforcedOptions[_eid][_msgType]; // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options. if (enforced.length == 0) return _extraOptions; // No caller options, return enforced if (_extraOptions.length == 0) return enforced; // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined. if (_extraOptions.length >= 2) { _assertOptionsType3(_extraOptions); // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced. return bytes.concat(enforced, _extraOptions[2:]); } // No valid set of options was found. revert InvalidOptions(_extraOptions); } /** * @dev Internal function to assert that options are of type 3. * @param _options The options to be checked. */ function _assertOptionsType3(bytes calldata _options) internal pure virtual { uint16 optionsType = uint16(bytes2(_options[0:2])); if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IOFT, OFTCore } from "./OFTCore.sol"; /** * @title OFT Contract * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract. */ abstract contract OFT is OFTCore, ERC20 { /** * @dev Constructor for the OFT contract. * @param _name The name of the OFT. * @param _symbol The symbol of the OFT. * @param _lzEndpoint The LayerZero endpoint address. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _delegate ) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {} /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) { return (type(IOFT).interfaceId, 1); } /** * @dev Retrieves the address of the underlying ERC20 implementation. * @return The address of the OFT token. * * @dev In the case of OFT, address(this) and erc20 are the same contract. */ function token() external view returns (address) { return address(this); } /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev In the case of OFT where the contract IS the token, approval is NOT required. */ function approvalRequired() external pure virtual returns (bool) { return false; } /** * @dev Burns tokens from the sender's specified balance. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debit( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90, // therefore amountSentLD CAN differ from amountReceivedLD. // @dev Default OFT burns on src. _burn(msg.sender, amountSentLD); } /** * @dev Credits tokens to the specified address. * @param _to The address to credit the tokens to. * @param _amountLD The amount of tokens to credit in local decimals. * @dev _srcEid The source chain ID. * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals. */ function _credit( address _to, uint256 _amountLD, uint32 /*_srcEid*/ ) internal virtual override returns (uint256 amountReceivedLD) { // @dev Default OFT mints on dst. _mint(_to, _amountLD); // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OApp, Origin } from "../oapp/OApp.sol"; import { OAppOptionsType3 } from "../oapp/libs/OAppOptionsType3.sol"; import { IOAppMsgInspector } from "../oapp/interfaces/IOAppMsgInspector.sol"; import { OAppPreCrimeSimulator } from "../precrime/OAppPreCrimeSimulator.sol"; import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol"; import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol"; import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol"; /** * @title OFTCore * @dev Abstract contract for the OftChain (OFT) token. */ abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 { using OFTMsgCodec for bytes; using OFTMsgCodec for bytes32; // @notice Provides a conversion rate when swapping between denominations of SD and LD // - shareDecimals == SD == shared Decimals // - localDecimals == LD == local decimals // @dev Considers that tokens have different decimal amounts on various chains. // @dev eg. // For a token // - locally with 4 decimals --> 1.2345 => uint(12345) // - remotely with 2 decimals --> 1.23 => uint(123) // - The conversion rate would be 10 ** (4 - 2) = 100 // @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote, // you can only display 1.23 -> uint(123). // @dev To preserve the dust that would otherwise be lost on that conversion, // we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh uint256 public immutable decimalConversionRate; // @notice Msg types that are used to identify the various OFT operations. // @dev This can be extended in child contracts for non-default oft operations // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol. uint16 public constant SEND = 1; uint16 public constant SEND_AND_CALL = 2; // Address of an optional contract to inspect both 'message' and 'options' address public msgInspector; event MsgInspectorSet(address inspector); /** * @dev Constructor. * @param _localDecimals The decimals of the token on the local chain (this chain). * @param _endpoint The address of the LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) { if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals(); decimalConversionRate = 10 ** (_localDecimals - sharedDecimals()); } /** * @dev Retrieves the shared decimals of the OFT. * @return The shared decimals of the OFT. * * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap * Lowest common decimal denominator between chains. * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64). * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller. * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615 */ function sharedDecimals() public pure virtual returns (uint8) { return 6; } /** * @dev Sets the message inspector address for the OFT. * @param _msgInspector The address of the message inspector. * * @dev This is an optional contract that can be used to inspect both 'message' and 'options'. * @dev Set it to address(0) to disable it, or set it to a contract address to enable it. */ function setMsgInspector(address _msgInspector) public virtual onlyOwner { msgInspector = _msgInspector; emit MsgInspectorSet(_msgInspector); } /** * @notice Provides a quote for OFT-related operations. * @param _sendParam The parameters for the send operation. * @return oftLimit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return oftReceipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view virtual returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt) { uint256 minAmountLD = 0; // Unused in the default implementation. uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation. oftLimit = OFTLimit(minAmountLD, maxAmountLD); // Unused in the default implementation; reserved for future complex fee details. oftFeeDetails = new OFTFeeDetail[](0); // @dev This is the same as the send() operation, but without the actual send. // - amountSentLD is the amount in local decimals that would be sent from the sender. // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance. // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does. (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView( _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); } /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return msgFee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend( SendParam calldata _sendParam, bool _payInLzToken ) external view virtual returns (MessagingFee memory msgFee) { // @dev mock the amount to receive, this is the same operation used in the send(). // The quote is as similar as possible to the actual send() operation. (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Calculates the LayerZero fee for the send() operation. return _quote(_sendParam.dstEid, message, options, _payInLzToken); } /** * @dev Executes the send operation. * @param _sendParam The parameters for the send operation. * @param _fee The calculated fee for the send() operation. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds. * @return msgReceipt The receipt for the send operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) { // @dev Applies the token transfers regarding this send() operation. // - amountSentLD is the amount in local decimals that was ACTUALLY sent from the sender. // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance. (uint256 amountSentLD, uint256 amountReceivedLD) = _debit( _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt. msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress); // @dev Formulate the OFT receipt. oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD); } /** * @dev Internal function to build the message and options. * @param _sendParam The parameters for the send() operation. * @param _amountLD The amount in local decimals. * @return message The encoded message. * @return options The encoded options. */ function _buildMsgAndOptions( SendParam calldata _sendParam, uint256 _amountLD ) internal view virtual returns (bytes memory message, bytes memory options) { bool hasCompose; // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is. (message, hasCompose) = OFTMsgCodec.encode( _sendParam.to, _toSD(_amountLD), // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote. // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01' _sendParam.composeMsg ); // @dev Change the msg type depending if its composed or not. uint16 msgType = hasCompose ? SEND_AND_CALL : SEND; // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3. options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions); // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector. // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean if (msgInspector != address(0)) IOAppMsgInspector(msgInspector).inspect(message, options); } /** * @dev Internal function to handle the receive on the LayerZero endpoint. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The encoded message. * @dev _executor The address of the executor. * @dev _extraData Additional data. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address /*_executor*/, // @dev unused in the default implementation. bytes calldata /*_extraData*/ // @dev unused in the default implementation. ) internal virtual override { // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm) // Thus everything is bytes32() encoded in flight. address toAddress = _message.sendTo().bytes32ToAddress(); // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid); if (_message.isComposed()) { // @dev Proprietary composeMsg format for the OFT. bytes memory composeMsg = OFTComposeMsgCodec.encode( _origin.nonce, _origin.srcEid, amountReceivedLD, _message.composeMsg() ); // @dev Stores the lzCompose payload that will be executed in a separate tx. // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains. // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed. // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive. // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0. endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg); } emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD); } /** * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The LayerZero message. * @param _executor The address of the off-chain executor. * @param _extraData Arbitrary data passed by the msg executor. * * @dev Enables the preCrime simulator to mock sending lzReceive() messages, * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver. */ function _lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual override { _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Check if the peer is considered 'trusted' by the OApp. * @param _eid The endpoint ID to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. * * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source. */ function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) { return peers[_eid] == _peer; } /** * @dev Internal function to remove dust from the given local decimal amount. * @param _amountLD The amount in local decimals. * @return amountLD The amount after removing dust. * * @dev Prevents the loss of dust when moving amounts between chains with different decimals. * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100). */ function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) { return (_amountLD / decimalConversionRate) * decimalConversionRate; } /** * @dev Internal function to convert an amount from shared decimals into local decimals. * @param _amountSD The amount in shared decimals. * @return amountLD The amount in local decimals. */ function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) { return _amountSD * decimalConversionRate; } /** * @dev Internal function to convert an amount from local decimals into shared decimals. * @param _amountLD The amount in local decimals. * @return amountSD The amount in shared decimals. */ function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) { return uint64(_amountLD / decimalConversionRate); } /** * @dev Internal function to mock the amount mutation from a OFT debit() operation. * @param _amountLD The amount to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @dev _dstEid The destination endpoint ID. * @return amountSentLD The amount sent, in local decimals. * @return amountReceivedLD The amount to be received on the remote chain, in local decimals. * * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote. */ function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 /*_dstEid*/ ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) { // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token. amountSentLD = _removeDust(_amountLD); // @dev The amount to send is the same as amount received in the default implementation. amountReceivedLD = amountSentLD; // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } /** * @dev Internal function to perform a debit operation. * @param _amountLD The amount to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination endpoint ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _debit( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD); /** * @dev Internal function to perform a credit operation. * @param _to The address to credit. * @param _amountLD The amount to credit in local decimals. * @param _srcEid The source endpoint ID. * @return amountReceivedLD The amount ACTUALLY received in local decimals. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _credit( address _to, uint256 _amountLD, uint32 _srcEid ) internal virtual returns (uint256 amountReceivedLD); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { MessagingReceipt, MessagingFee } from "../../oapp/OAppSender.sol"; /** * @dev Struct representing token parameters for the OFT send() operation. */ struct SendParam { uint32 dstEid; // Destination endpoint ID. bytes32 to; // Recipient address. uint256 amountLD; // Amount to send in local decimals. uint256 minAmountLD; // Minimum amount to send in local decimals. bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message. bytes composeMsg; // The composed message for the send() operation. bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. } /** * @dev Struct representing OFT limit information. * @dev These amounts can change dynamically and are up the the specific oft implementation. */ struct OFTLimit { uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient. uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient. } /** * @dev Struct representing OFT receipt information. */ struct OFTReceipt { uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals. // @dev In non-default implementations, the amountReceivedLD COULD differ from this value. uint256 amountReceivedLD; // Amount of tokens to be received on the remote side. } /** * @dev Struct representing OFT fee details. * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI. */ struct OFTFeeDetail { int256 feeAmountLD; // Amount of the fee in local decimals. string description; // Description of the fee. } /** * @title IOFT * @dev Interface for the OftChain (OFT) token. * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well. * @dev This specific interface ID is '0x02e49c2c'. */ interface IOFT { // Custom error messages error InvalidLocalDecimals(); error SlippageExceeded(uint256 amountLD, uint256 minAmountLD); // Events event OFTSent( bytes32 indexed guid, // GUID of the OFT message. uint32 dstEid, // Destination Endpoint ID. address indexed fromAddress, // Address of the sender on the src chain. uint256 amountLD // Amount of tokens sent in local decimals. ); event OFTReceived( bytes32 indexed guid, // GUID of the OFT message. uint32 srcEid, // Source Endpoint ID. address indexed toAddress, // Address of the recipient on the dst chain. uint256 amountLD // Amount of tokens received in local decimals. ); /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external view returns (bytes4 interfaceId, uint64 version); /** * @notice Retrieves the address of the token associated with the OFT. * @return token The address of the ERC20 token implementation. */ function token() external view returns (address); /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev Allows things like wallet implementers to determine integration requirements, * without understanding the underlying token implementation. */ function approvalRequired() external view returns (bool); /** * @notice Retrieves the shared decimals of the OFT. * @return sharedDecimals The shared decimals of the OFT. */ function sharedDecimals() external view returns (uint8); /** * @notice Provides a quote for OFT-related operations. * @param _sendParam The parameters for the send operation. * @return limit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return receipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory); /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return fee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory); /** * @notice Executes the send() operation. * @param _sendParam The parameters for the send operation. * @param _fee The fee information supplied by the caller. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds from fees etc. on the src. * @return receipt The LayerZero messaging receipt from the send() operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable returns (MessagingReceipt memory, OFTReceipt memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library OFTComposeMsgCodec { // Offset constants for decoding composed messages uint8 private constant NONCE_OFFSET = 8; uint8 private constant SRC_EID_OFFSET = 12; uint8 private constant AMOUNT_LD_OFFSET = 44; uint8 private constant COMPOSE_FROM_OFFSET = 76; /** * @dev Encodes a OFT composed message. * @param _nonce The nonce value. * @param _srcEid The source endpoint ID. * @param _amountLD The amount in local decimals. * @param _composeMsg The composed message. * @return _msg The encoded Composed message. */ function encode( uint64 _nonce, uint32 _srcEid, uint256 _amountLD, bytes memory _composeMsg // 0x[composeFrom][composeMsg] ) internal pure returns (bytes memory _msg) { _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg); } /** * @dev Retrieves the nonce from the composed message. * @param _msg The message. * @return The nonce value. */ function nonce(bytes calldata _msg) internal pure returns (uint64) { return uint64(bytes8(_msg[:NONCE_OFFSET])); } /** * @dev Retrieves the source endpoint ID from the composed message. * @param _msg The message. * @return The source endpoint ID. */ function srcEid(bytes calldata _msg) internal pure returns (uint32) { return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET])); } /** * @dev Retrieves the amount in local decimals from the composed message. * @param _msg The message. * @return The amount in local decimals. */ function amountLD(bytes calldata _msg) internal pure returns (uint256) { return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET])); } /** * @dev Retrieves the composeFrom value from the composed message. * @param _msg The message. * @return The composeFrom value. */ function composeFrom(bytes calldata _msg) internal pure returns (bytes32) { return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]); } /** * @dev Retrieves the composed message. * @param _msg The message. * @return The composed message. */ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) { return _msg[COMPOSE_FROM_OFFSET:]; } /** * @dev Converts an address to bytes32. * @param _addr The address to convert. * @return The bytes32 representation of the address. */ function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } /** * @dev Converts bytes32 to an address. * @param _b The bytes32 value to convert. * @return The address representation of bytes32. */ function bytes32ToAddress(bytes32 _b) internal pure returns (address) { return address(uint160(uint256(_b))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library OFTMsgCodec { // Offset constants for encoding and decoding OFT messages uint8 private constant SEND_TO_OFFSET = 32; uint8 private constant SEND_AMOUNT_SD_OFFSET = 40; /** * @dev Encodes an OFT LayerZero message. * @param _sendTo The recipient address. * @param _amountShared The amount in shared decimals. * @param _composeMsg The composed message. * @return _msg The encoded message. * @return hasCompose A boolean indicating whether the message has a composed payload. */ function encode( bytes32 _sendTo, uint64 _amountShared, bytes memory _composeMsg ) internal view returns (bytes memory _msg, bool hasCompose) { hasCompose = _composeMsg.length > 0; // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src. _msg = hasCompose ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg) : abi.encodePacked(_sendTo, _amountShared); } /** * @dev Checks if the OFT message is composed. * @param _msg The OFT message. * @return A boolean indicating whether the message is composed. */ function isComposed(bytes calldata _msg) internal pure returns (bool) { return _msg.length > SEND_AMOUNT_SD_OFFSET; } /** * @dev Retrieves the recipient address from the OFT message. * @param _msg The OFT message. * @return The recipient address. */ function sendTo(bytes calldata _msg) internal pure returns (bytes32) { return bytes32(_msg[:SEND_TO_OFFSET]); } /** * @dev Retrieves the amount in shared decimals from the OFT message. * @param _msg The OFT message. * @return The amount in shared decimals. */ function amountSD(bytes calldata _msg) internal pure returns (uint64) { return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET])); } /** * @dev Retrieves the composed message from the OFT message. * @param _msg The OFT message. * @return The composed message. */ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) { return _msg[SEND_AMOUNT_SD_OFFSET:]; } /** * @dev Converts an address to bytes32. * @param _addr The address to convert. * @return The bytes32 representation of the address. */ function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } /** * @dev Converts bytes32 to an address. * @param _b The bytes32 value to convert. * @return The address representation of bytes32. */ function bytes32ToAddress(bytes32 _b) internal pure returns (address) { return address(uint160(uint256(_b))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IPreCrime } from "./interfaces/IPreCrime.sol"; import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol"; /** * @title OAppPreCrimeSimulator * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp. */ abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable { // The address of the preCrime implementation. address public preCrime; /** * @dev Retrieves the address of the OApp contract. * @return The address of the OApp contract. * * @dev The simulator contract is the base contract for the OApp by default. * @dev If the simulator is a separate contract, override this function. */ function oApp() external view virtual returns (address) { return address(this); } /** * @dev Sets the preCrime contract address. * @param _preCrime The address of the preCrime contract. */ function setPreCrime(address _preCrime) public virtual onlyOwner { preCrime = _preCrime; emit PreCrimeSet(_preCrime); } /** * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results. * @param _packets An array of InboundPacket objects representing received packets to be delivered. * * @dev WARNING: MUST revert at the end with the simulation results. * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function, * WITHOUT actually executing them. */ function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual { for (uint256 i = 0; i < _packets.length; i++) { InboundPacket calldata packet = _packets[i]; // Ignore packets that are not from trusted peers. if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue; // @dev Because a verifier is calling this function, it doesnt have access to executor params: // - address _executor // - bytes calldata _extraData // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive(). // They are instead stubbed to default values, address(0) and bytes("") // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit, // which would cause the revert to be ignored. this.lzReceiveSimulate{ value: packet.value }( packet.origin, packet.guid, packet.message, packet.executor, packet.extraData ); } // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult(). revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult()); } /** * @dev Is effectively an internal function because msg.sender must be address(this). * Allows resetting the call stack for 'internal' calls. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier of the packet. * @param _message The message payload of the packet. * @param _executor The executor address for the packet. * @param _extraData Additional data for the packet. */ function lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable virtual { // @dev Ensure ONLY can be called 'internally'. if (msg.sender != address(this)) revert OnlySelf(); _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The GUID of the LayerZero message. * @param _message The LayerZero message. * @param _executor The address of the off-chain executor. * @param _extraData Arbitrary data passed by the msg executor. * * @dev Enables the preCrime simulator to mock sending lzReceive() messages, * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver. */ function _lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; /** * @dev checks if the specified peer is considered 'trusted' by the OApp. * @param _eid The endpoint Id to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. */ function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers. // solhint-disable-next-line no-unused-import import { InboundPacket, Origin } from "../libs/Packet.sol"; /** * @title IOAppPreCrimeSimulator Interface * @dev Interface for the preCrime simulation functionality in an OApp. */ interface IOAppPreCrimeSimulator { // @dev simulation result used in PreCrime implementation error SimulationResult(bytes result); error OnlySelf(); /** * @dev Emitted when the preCrime contract address is set. * @param preCrimeAddress The address of the preCrime contract. */ event PreCrimeSet(address preCrimeAddress); /** * @dev Retrieves the address of the preCrime contract implementation. * @return The address of the preCrime contract. */ function preCrime() external view returns (address); /** * @dev Retrieves the address of the OApp contract. * @return The address of the OApp contract. */ function oApp() external view returns (address); /** * @dev Sets the preCrime contract address. * @param _preCrime The address of the preCrime contract. */ function setPreCrime(address _preCrime) external; /** * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result. * @param _packets An array of LayerZero InboundPacket objects representing received packets. */ function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable; /** * @dev checks if the specified peer is considered 'trusted' by the OApp. * @param _eid The endpoint Id to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. */ function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; struct PreCrimePeer { uint32 eid; bytes32 preCrime; bytes32 oApp; } // TODO not done yet interface IPreCrime { error OnlyOffChain(); // for simulate() error PacketOversize(uint256 max, uint256 actual); error PacketUnsorted(); error SimulationFailed(bytes reason); // for preCrime() error SimulationResultNotFound(uint32 eid); error InvalidSimulationResult(uint32 eid, bytes reason); error CrimeFound(bytes crime); function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory); function simulate( bytes[] calldata _packets, uint256[] calldata _packetMsgValues ) external payable returns (bytes memory); function buildSimulationResult() external view returns (bytes memory); function preCrime( bytes[] calldata _packets, uint256[] calldata _packetMsgValues, bytes[] calldata _simulations ) external; function version() external view returns (uint64 major, uint8 minor); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol"; /** * @title InboundPacket * @dev Structure representing an inbound packet received by the contract. */ struct InboundPacket { Origin origin; // Origin information of the packet. uint32 dstEid; // Destination endpointId of the packet. address receiver; // Receiver address for the packet. bytes32 guid; // Unique identifier of the packet. uint256 value; // msg.value of the packet. address executor; // Executor address for the packet. bytes message; // Message payload of the packet. bytes extraData; // Additional arbitrary data for the packet. } /** * @title PacketDecoder * @dev Library for decoding LayerZero packets. */ library PacketDecoder { using PacketV1Codec for bytes; /** * @dev Decode an inbound packet from the given packet data. * @param _packet The packet data to decode. * @return packet An InboundPacket struct representing the decoded packet. */ function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) { packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce()); packet.dstEid = _packet.dstEid(); packet.receiver = _packet.receiverB20(); packet.guid = _packet.guid(); packet.message = _packet.message(); } /** * @dev Decode multiple inbound packets from the given packet data and associated message values. * @param _packets An array of packet data to decode. * @param _packetMsgValues An array of associated message values for each packet. * @return packets An array of InboundPacket structs representing the decoded packets. */ function decode( bytes[] calldata _packets, uint256[] memory _packetMsgValues ) internal pure returns (InboundPacket[] memory packets) { packets = new InboundPacket[](_packets.length); for (uint256 i = 0; i < _packets.length; i++) { bytes calldata packet = _packets[i]; packets[i] = PacketDecoder.decode(packet); // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive. packets[i].value = _packetMsgValues[i]; } } }
// SPDX-License-Identifier: MIT 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.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; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { SetConfigParam } from "./IMessageLibManager.sol"; enum MessageLibType { Send, Receive, SendAndReceive } interface IMessageLib is IERC165 { function setConfig(address _oapp, SetConfigParam[] calldata _config) external; function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config); function isSupportedEid(uint32 _eid) external view returns (bool); // message libs of same major version are compatible function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion); function messageLibType() external view returns (MessageLibType); }
// SPDX-License-Identifier: MIT 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 _timeout) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
// 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; interface IMessagingContext { function isSendingMessage() external view returns (bool); function getSendContext() external view returns (uint32 dstEid, address sender); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { MessagingFee } from "./ILayerZeroEndpointV2.sol"; import { IMessageLib } from "./IMessageLib.sol"; struct Packet { uint64 nonce; uint32 srcEid; address sender; uint32 dstEid; bytes32 receiver; bytes32 guid; bytes message; } interface ISendLib is IMessageLib { function send( Packet calldata _packet, bytes calldata _options, bool _payInLzToken ) external returns (MessagingFee memory, bytes memory encodedPacket); function quote( Packet calldata _packet, bytes calldata _options, bool _payInLzToken ) external view returns (MessagingFee memory); function setTreasury(address _treasury) external; function withdrawFee(address _to, uint256 _amount) external; function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external; }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; library AddressCast { error AddressCast_InvalidSizeForAddress(); error AddressCast_InvalidAddress(); function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) { if (_addressBytes.length > 32) revert AddressCast_InvalidAddress(); result = bytes32(_addressBytes); unchecked { uint256 offset = 32 - _addressBytes.length; result = result >> (offset * 8); } } function toBytes32(address _address) internal pure returns (bytes32 result) { result = bytes32(uint256(uint160(_address))); } function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) { if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress(); result = new bytes(_size); unchecked { uint256 offset = 256 - _size * 8; assembly { mstore(add(result, 32), shl(offset, _addressBytes32)) } } } function toAddress(bytes32 _addressBytes32) internal pure returns (address result) { result = address(uint160(uint256(_addressBytes32))); } function toAddress(bytes calldata _addressBytes) internal pure returns (address result) { if (_addressBytes.length != 20) revert AddressCast_InvalidAddress(); result = address(bytes20(_addressBytes)); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { Packet } from "../../interfaces/ISendLib.sol"; import { AddressCast } from "../../libs/AddressCast.sol"; library PacketV1Codec { using AddressCast for address; using AddressCast for bytes32; uint8 internal constant PACKET_VERSION = 1; // header (version + nonce + path) // version uint256 private constant PACKET_VERSION_OFFSET = 0; // nonce uint256 private constant NONCE_OFFSET = 1; // path uint256 private constant SRC_EID_OFFSET = 9; uint256 private constant SENDER_OFFSET = 13; uint256 private constant DST_EID_OFFSET = 45; uint256 private constant RECEIVER_OFFSET = 49; // payload (guid + message) uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path) uint256 private constant MESSAGE_OFFSET = 113; function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) { encodedPacket = abi.encodePacked( PACKET_VERSION, _packet.nonce, _packet.srcEid, _packet.sender.toBytes32(), _packet.dstEid, _packet.receiver, _packet.guid, _packet.message ); } function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) { return abi.encodePacked( PACKET_VERSION, _packet.nonce, _packet.srcEid, _packet.sender.toBytes32(), _packet.dstEid, _packet.receiver ); } function encodePayload(Packet memory _packet) internal pure returns (bytes memory) { return abi.encodePacked(_packet.guid, _packet.message); } function header(bytes calldata _packet) internal pure returns (bytes calldata) { return _packet[0:GUID_OFFSET]; } function version(bytes calldata _packet) internal pure returns (uint8) { return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET])); } function nonce(bytes calldata _packet) internal pure returns (uint64) { return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET])); } function srcEid(bytes calldata _packet) internal pure returns (uint32) { return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET])); } function sender(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]); } function senderAddressB20(bytes calldata _packet) internal pure returns (address) { return sender(_packet).toAddress(); } function dstEid(bytes calldata _packet) internal pure returns (uint32) { return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET])); } function receiver(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]); } function receiverB20(bytes calldata _packet) internal pure returns (address) { return receiver(_packet).toAddress(); } function guid(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]); } function message(bytes calldata _packet) internal pure returns (bytes calldata) { return bytes(_packet[MESSAGE_OFFSET:]); } function payload(bytes calldata _packet) internal pure returns (bytes calldata) { return bytes(_packet[GUID_OFFSET:]); } function payloadHash(bytes calldata _packet) internal pure returns (bytes32) { return keccak256(payload(_packet)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ 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 pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // 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 { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.22; import "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; contract MaviaOFT is OFT { constructor( string memory _name, // token name string memory _symbol, // token symbol address _layerZeroEndpoint, // local endpoint address address _owner // token owner used as a delegate in LayerZero Endpoint ) OFT(_name, _symbol, _layerZeroEndpoint, _owner) Ownable() // solhint-disable-next-line no-empty-blocks {} }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "shanghai", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_layerZeroEndpoint","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"composeMsgSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405234801562000010575f80fd5b50604051620039ac380380620039ac833981016040819052620000339162000292565b83838383838360128484818181816200004c3362000161565b6001600160a01b0380831660805281166200007a57604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e1906024015f604051808303815f87803b158015620000bf575f80fd5b505af1158015620000d2573d5f803e3d5ffd5b5050505050505050620000ea620001b060201b60201c565b60ff168360ff16101562000111576040516301e9714b60e41b815260040160405180910390fd5b6200011e60068462000330565b6200012b90600a6200044b565b60a05250600891506200014190508382620004ec565b506009620001508282620004ec565b5050505050505050505050620005b8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600690565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001d9575f80fd5b81516001600160401b0380821115620001f657620001f6620001b5565b604051601f8301601f19908116603f01168101908282118183101715620002215762000221620001b5565b81604052838152602092508660208588010111156200023e575f80fd5b5f91505b8382101562000261578582018301518183018401529082019062000242565b5f602085830101528094505050505092915050565b80516001600160a01b03811681146200028d575f80fd5b919050565b5f805f8060808587031215620002a6575f80fd5b84516001600160401b0380821115620002bd575f80fd5b620002cb88838901620001c9565b95506020870151915080821115620002e1575f80fd5b50620002f087828801620001c9565b935050620003016040860162000276565b9150620003116060860162000276565b905092959194509250565b634e487b7160e01b5f52601160045260245ffd5b60ff82811682821603908111156200034c576200034c6200031c565b92915050565b600181815b808511156200039257815f19048211156200037657620003766200031c565b808516156200038457918102915b93841c939080029062000357565b509250929050565b5f82620003aa575060016200034c565b81620003b857505f6200034c565b8160018114620003d15760028114620003dc57620003fc565b60019150506200034c565b60ff841115620003f057620003f06200031c565b50506001821b6200034c565b5060208310610133831016604e8410600b841016171562000421575081810a6200034c565b6200042d838362000352565b805f19048211156200044357620004436200031c565b029392505050565b5f6200045b60ff8416836200039a565b9392505050565b600181811c908216806200047757607f821691505b6020821081036200049657634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620004e757805f5260205f20601f840160051c81016020851015620004c35750805b601f840160051c820191505b81811015620004e4575f8155600101620004cf565b50505b505050565b81516001600160401b03811115620005085762000508620001b5565b620005208162000519845462000462565b846200049c565b602080601f83116001811462000556575f84156200053e5750858301515b5f19600386901b1c1916600185901b178555620005b0565b5f85815260208120601f198616915b82811015620005865788860151825594840194600190910190840162000565565b5085821015620005a457878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b60805160a05161338c620006205f395f818161060c01528181611e0801528181611e7a0152611f3d01525f81816104f601528181610980015281816113b6015281816117b701528181611b8501528181611d30015281816121510152612208015261338c5ff3fe60806040526004361061025f575f3560e01c80637d25a05e1161013f578063bb0b6a53116100b3578063d045a0dc11610078578063d045a0dc14610759578063d42438851461076c578063dd62ed3e1461078b578063f2fde38b146107cf578063fc0c546a1461047f578063ff7bd03d146107ee575f80fd5b8063bb0b6a53146106bc578063bc70b354146106e7578063bd815db014610706578063c7c7f5b314610719578063ca5eb5e11461073a575f80fd5b80639f68b964116101045780639f68b9641461062e578063a457c2d714610640578063a9059cbb1461065f578063b731ea0a1461067e578063b92d0eff1461047f578063b98bd0701461069d575f80fd5b80637d25a05e1461057f578063857749b0146105b85780638da5cb5b146105cb57806395d89b41146105e7578063963efcaa146105fb575f80fd5b8063313ce567116101d65780635535d4611161019b5780635535d461146104915780635a0dfe4d146104b05780635e280f11146104e55780636fc1b31e1461051857806370a0823114610537578063715018a61461056b575f80fd5b8063313ce567146103f45780633400288b1461041557806339509351146104345780633b6f743b1461045357806352ae28791461047f575f80fd5b8063134d4f2511610227578063134d4f2514610336578063156a0d0f1461035d57806317442b701461038357806318160ddd146103a35780631f5e1334146103c157806323b872dd146103d5575f80fd5b806306fdde0314610263578063095ea7b31461028d5780630d35b415146102bc578063111ecdad146102ea57806313137d6514610321575b5f80fd5b34801561026e575f80fd5b5061027761080d565b60405161028491906125a7565b60405180910390f35b348015610298575f80fd5b506102ac6102a73660046125cd565b61089d565b6040519015158152602001610284565b3480156102c7575f80fd5b506102db6102d636600461260d565b6108b3565b6040516102849392919061263e565b3480156102f5575f80fd5b50600454610309906001600160a01b031681565b6040516001600160a01b039091168152602001610284565b61033461032f366004612729565b61097e565b005b348015610341575f80fd5b5061034a600281565b60405161ffff9091168152602001610284565b348015610368575f80fd5b506040805162b9270b60e21b81526001602082015201610284565b34801561038e575f80fd5b50604080516001808252602082015201610284565b3480156103ae575f80fd5b506007545b604051908152602001610284565b3480156103cc575f80fd5b5061034a600181565b3480156103e0575f80fd5b506102ac6103ef3660046127c1565b610a3e565b3480156103ff575f80fd5b5060125b60405160ff9091168152602001610284565b348015610420575f80fd5b5061033461042f366004612817565b610ae8565b34801561043f575f80fd5b506102ac61044e3660046125cd565b610b66565b34801561045e575f80fd5b5061047261046d36600461283e565b610ba1565b604051610284919061288c565b34801561048a575f80fd5b5030610309565b34801561049c575f80fd5b506102776104ab3660046128b4565b610c05565b3480156104bb575f80fd5b506102ac6104ca366004612817565b63ffffffff919091165f908152600160205260409020541490565b3480156104f0575f80fd5b506103097f000000000000000000000000000000000000000000000000000000000000000081565b348015610523575f80fd5b506103346105323660046128e5565b610ca7565b348015610542575f80fd5b506103b36105513660046128e5565b6001600160a01b03165f9081526005602052604090205490565b348015610576575f80fd5b50610334610d25565b34801561058a575f80fd5b506105a0610599366004612817565b5f92915050565b6040516001600160401b039091168152602001610284565b3480156105c3575f80fd5b506006610403565b3480156105d6575f80fd5b505f546001600160a01b0316610309565b3480156105f2575f80fd5b50610277610d59565b348015610606575f80fd5b506103b37f000000000000000000000000000000000000000000000000000000000000000081565b348015610639575f80fd5b505f6102ac565b34801561064b575f80fd5b506102ac61065a3660046125cd565b610d68565b34801561066a575f80fd5b506102ac6106793660046125cd565b610e00565b348015610689575f80fd5b50600254610309906001600160a01b031681565b3480156106a8575f80fd5b506103346106b7366004612940565b610e0c565b3480156106c7575f80fd5b506103b36106d636600461297e565b60016020525f908152604090205481565b3480156106f2575f80fd5b50610277610701366004612997565b610f89565b610334610714366004612940565b6110fe565b61072c6107273660046129f3565b61127e565b604051610284929190612a5b565b348015610745575f80fd5b506103346107543660046128e5565b61136e565b610334610767366004612729565b611410565b348015610777575f80fd5b506103346107863660046128e5565b61143f565b348015610796575f80fd5b506103b36107a5366004612aac565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205490565b3480156107da575f80fd5b506103346107e93660046128e5565b6114b6565b3480156107f9575f80fd5b506102ac610808366004612ad8565b611550565b60606008805461081c90612af2565b80601f016020809104026020016040519081016040528092919081815260200182805461084890612af2565b80156108935780601f1061086a57610100808354040283529160200191610893565b820191905f5260205f20905b81548152906001019060200180831161087657829003601f168201915b5050505050905090565b5f6108a9338484611584565b5060015b92915050565b604080518082019091525f808252602082015260606108e360405180604001604052805f81526020015f81525090565b6040805180820182525f8082526001600160401b0360208084018290528451838152908101909452919550918261093c565b604080518082019091525f8152606060208201528152602001906001900390816109155790505b5093505f80610960604089013560608a013561095b60208c018c61297e565b6116a7565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146109ce576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b602087018035906109e8906109e3908a61297e565b6116ea565b14610a26576109fa602088018861297e565b60405163309afaf360e21b815263ffffffff9091166004820152602088013560248201526044016109c5565b610a3587878787878787611725565b50505050505050565b5f610a4a848484611883565b6001600160a01b0384165f90815260066020908152604080832033845290915290205482811015610ace5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016109c5565b610adb8533858403611584565b60019150505b9392505050565b5f546001600160a01b03163314610b115760405162461bcd60e51b81526004016109c590612b38565b63ffffffff82165f81815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a15050565b335f8181526006602090815260408083206001600160a01b038716845290915281205490916108a9918590610b9c908690612b81565b611584565b604080518082019091525f80825260208201525f610bcf6040850135606086013561095b602088018861297e565b9150505f80610bde8684611a51565b9092509050610bfb610bf3602088018861297e565b838388611b70565b9695505050505050565b600360209081525f928352604080842090915290825290208054610c2890612af2565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5490612af2565b8015610c9f5780601f10610c7657610100808354040283529160200191610c9f565b820191905f5260205f20905b815481529060010190602001808311610c8257829003601f168201915b505050505081565b5f546001600160a01b03163314610cd05760405162461bcd60e51b81526004016109c590612b38565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b5f546001600160a01b03163314610d4e5760405162461bcd60e51b81526004016109c590612b38565b610d575f611c4e565b565b60606009805461081c90612af2565b335f9081526006602090815260408083206001600160a01b038616845290915281205482811015610de95760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016109c5565b610df63385858403611584565b5060019392505050565b5f6108a9338484611883565b5f546001600160a01b03163314610e355760405162461bcd60e51b81526004016109c590612b38565b5f5b81811015610f5757610e79838383818110610e5457610e54612b94565b9050602002810190610e669190612ba8565b610e74906040810190612bc6565b611c9d565b828282818110610e8b57610e8b612b94565b9050602002810190610e9d9190612ba8565b610eab906040810190612bc6565b60035f868686818110610ec057610ec0612b94565b9050602002810190610ed29190612ba8565b610ee090602081019061297e565b63ffffffff1663ffffffff1681526020019081526020015f205f868686818110610f0c57610f0c612b94565b9050602002810190610f1e9190612ba8565b610f2f906040810190602001612c08565b61ffff16815260208101919091526040015f2091610f4e919083612c65565b50600101610e37565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6748282604051610b5a929190612d46565b63ffffffff84165f90815260036020908152604080832061ffff87168452909152812080546060929190610fbc90612af2565b80601f0160208091040260200160405190810160405280929190818152602001828054610fe890612af2565b80156110335780601f1061100a57610100808354040283529160200191611033565b820191905f5260205f20905b81548152906001019060200180831161101657829003601f168201915b5050505050905080515f036110815783838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509294506110f69350505050565b5f8390036110905790506110f6565b600283106110d9576110a28484611c9d565b806110b08460028188612e25565b6040516020016110c293929190612e4c565b6040516020818303038152906040529150506110f6565b8383604051639a6d49cd60e01b81526004016109c5929190612e72565b949350505050565b5f5b81811015611201573683838381811061111b5761111b612b94565b905060200281019061112d9190612e85565b905061115f61113f602083018361297e565b602083013563ffffffff919091165f908152600160205260409020541490565b61116957506111f9565b3063d045a0dc60c08301358360a0810135611188610100830183612bc6565b611199610100890160e08a016128e5565b6111a76101208a018a612bc6565b6040518963ffffffff1660e01b81526004016111c99796959493929190612eae565b5f604051808303818588803b1580156111e0575f80fd5b505af11580156111f2573d5f803e3d5ffd5b5050505050505b600101611100565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b81526004015f60405180830381865afa15801561123d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112649190810190612f5b565b604051638351eea760e01b81526004016109c591906125a7565b611286612517565b604080518082019091525f80825260208201525f806112ba604088013560608901356112b560208b018b61297e565b611ce3565b915091505f806112ca8984611a51565b90925090506112f66112df60208b018b61297e565b83836112f0368d90038d018d612ff7565b8b611cff565b60408051808201909152858152602080820186905282519298509096503391907ffff873bb909b73d08a8c1af4b21779e87103bb8ea8cf3b3a0067eb8526b8b80a90611344908d018d61297e565b6040805163ffffffff9092168252602082018990520160405180910390a350505050935093915050565b5f546001600160a01b031633146113975760405162461bcd60e51b81526004016109c590612b38565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e1906024015f604051808303815f87803b1580156113f7575f80fd5b505af1158015611409573d5f803e3d5ffd5b5050505050565b3330146114305760405163029a949d60e31b815260040160405180910390fd5b610a3587878787878787610a26565b5f546001600160a01b031633146114685760405162461bcd60e51b81526004016109c590612b38565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610d1a565b5f546001600160a01b031633146114df5760405162461bcd60e51b81526004016109c590612b38565b6001600160a01b0381166115445760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109c5565b61154d81611c4e565b50565b5f602082018035906001908390611567908661297e565b63ffffffff16815260208101919091526040015f20541492915050565b6001600160a01b0383166115e65760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016109c5565b6001600160a01b0382166116475760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016109c5565b6001600160a01b038381165f8181526006602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f806116b285611e05565b9150819050838110156116e2576040516371c4efed60e01b815260048101829052602481018590526044016109c5565b935093915050565b63ffffffff81165f90815260016020526040812054806108ad5760405163f6ff4fb760e01b815263ffffffff841660048201526024016109c5565b5f6117366117338787611e3b565b90565b90505f6117618261174f61174a8a8a611e52565b611e74565b61175c60208d018d61297e565b611ea8565b90506028861115611821575f61179d61178060608c0160408d01613027565b61178d60208d018d61297e565b846117988c8c611ebb565b611f05565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906117f29086908d905f908790600401613042565b5f604051808303815f87803b158015611809575f80fd5b505af115801561181b573d5f803e3d5ffd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61185a60208d018d61297e565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383166118e75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016109c5565b6001600160a01b0382166119495760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016109c5565b6001600160a01b0383165f90815260056020526040902054818110156119c05760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016109c5565b6001600160a01b038085165f908152600560205260408082208585039055918516815290812080548492906119f6908490612b81565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a4291815260200190565b60405180910390a35b50505050565b6060805f611aac8560200135611a6686611f37565b611a7360a0890189612bc6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f6292505050565b90935090505f81611abe576001611ac1565b60025b9050611ae1611ad3602088018861297e565b8261070160808a018a612bc6565b6004549093506001600160a01b031615611b67576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb91611b26918891889101613072565b602060405180830381865afa158015611b41573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b659190613096565b505b50509250929050565b604080518082019091525f80825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611bd2896116ea565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611c079291906130b1565b6040805180830381865afa158015611c21573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c459190613157565b95945050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f611cab6002828486612e25565b611cb491613171565b60f01c905060038114611cde578282604051639a6d49cd60e01b81526004016109c5929190612e72565b505050565b5f80611cf08585856116a7565b90925090506116e23383611fdc565b611d07612517565b5f611d14845f0151612127565b602085015190915015611d2e57611d2e846020015161214e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611d7e8c6116ea565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401611db99291906130b1565b60806040518083038185885af1158015611dd5573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190611dfa91906131a1565b979650505050505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000611e318184613206565b6108ad9190613225565b5f611e496020828486612e25565b610ae19161323c565b5f611e61602860208486612e25565b611e6a91613259565b60c01c9392505050565b5f6108ad7f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416613225565b5f611eb38484612231565b509092915050565b6060611eca8260288186612e25565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929695505050505050565b606084848484604051602001611f1e9493929190613287565b6040516020818303038152906040529050949350505050565b5f6108ad7f000000000000000000000000000000000000000000000000000000000000000083613206565b8051606090151580611fab578484604051602001611f9792919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052611fd2565b84843385604051602001611fc294939291906132d5565b6040516020818303038152906040525b9150935093915050565b6001600160a01b03821661203c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016109c5565b6001600160a01b0382165f90815260056020526040902054818110156120af5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016109c5565b6001600160a01b0383165f9081526005602052604081208383039055600780548492906120dd908490613317565b90915550506040518281525f906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b5f81341461214a576040516304fb820960e51b81523460048201526024016109c5565b5090565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121cf919061332a565b90506001600160a01b0381166121f8576040516329b99a9560e11b815260040160405180910390fd5b61222d6001600160a01b038216337f00000000000000000000000000000000000000000000000000000000000000008561230d565b5050565b6001600160a01b0382166122875760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016109c5565b8060075f8282546122989190612b81565b90915550506001600160a01b0382165f90815260056020526040812080548392906122c4908490612b81565b90915550506040518181526001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152611a4b928792915f916123a4918516908490612421565b805190915015611cde57808060200190518101906123c29190613096565b611cde5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109c5565b60606110f684845f8585843b6124795760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109c5565b5f80866001600160a01b031685876040516124949190613345565b5f6040518083038185875af1925050503d805f81146124ce576040519150601f19603f3d011682016040523d82523d5f602084013e6124d3565b606091505b5091509150611dfa828286606083156124ed575081610ae1565b8251156124fd5782518084602001fd5b8160405162461bcd60e51b81526004016109c591906125a7565b60405180606001604052805f80191681526020015f6001600160401b0316815260200161255560405180604001604052805f81526020015f81525090565b905290565b5f5b8381101561257457818101518382015260200161255c565b50505f910152565b5f815180845261259381602086016020860161255a565b601f01601f19169290920160200192915050565b602081525f610ae1602083018461257c565b6001600160a01b038116811461154d575f80fd5b5f80604083850312156125de575f80fd5b82356125e9816125b9565b946020939093013593505050565b5f60e08284031215612607575f80fd5b50919050565b5f6020828403121561261d575f80fd5b81356001600160401b03811115612632575f80fd5b6110f6848285016125f7565b83518152602080850151908201525f60a08201604060a0604085015281865180845260c08601915060c08160051b870101935060208089015f5b838110156126b75788870360bf190185528151805188528301518388018790526126a48789018261257c565b9750509382019390820190600101612678565b505087516060880152505050602085015160808501525090506110f6565b5f60608284031215612607575f80fd5b5f8083601f8401126126f5575f80fd5b5081356001600160401b0381111561270b575f80fd5b602083019150836020828501011115612722575f80fd5b9250929050565b5f805f805f805f60e0888a03121561273f575f80fd5b61274989896126d5565b96506060880135955060808801356001600160401b038082111561276b575f80fd5b6127778b838c016126e5565b909750955060a08a0135915061278c826125b9565b90935060c089013590808211156127a1575f80fd5b506127ae8a828b016126e5565b989b979a50959850939692959293505050565b5f805f606084860312156127d3575f80fd5b83356127de816125b9565b925060208401356127ee816125b9565b929592945050506040919091013590565b803563ffffffff81168114612812575f80fd5b919050565b5f8060408385031215612828575f80fd5b6125e9836127ff565b801515811461154d575f80fd5b5f806040838503121561284f575f80fd5b82356001600160401b03811115612864575f80fd5b612870858286016125f7565b925050602083013561288181612831565b809150509250929050565b8151815260208083015190820152604081016108ad565b803561ffff81168114612812575f80fd5b5f80604083850312156128c5575f80fd5b6128ce836127ff565b91506128dc602084016128a3565b90509250929050565b5f602082840312156128f5575f80fd5b8135610ae1816125b9565b5f8083601f840112612910575f80fd5b5081356001600160401b03811115612926575f80fd5b6020830191508360208260051b8501011115612722575f80fd5b5f8060208385031215612951575f80fd5b82356001600160401b03811115612966575f80fd5b61297285828601612900565b90969095509350505050565b5f6020828403121561298e575f80fd5b610ae1826127ff565b5f805f80606085870312156129aa575f80fd5b6129b3856127ff565b93506129c1602086016128a3565b925060408501356001600160401b038111156129db575f80fd5b6129e7878288016126e5565b95989497509550505050565b5f805f8385036080811215612a06575f80fd5b84356001600160401b03811115612a1b575f80fd5b612a27878288016125f7565b9450506040601f1982011215612a3b575f80fd5b506020840191506060840135612a50816125b9565b809150509250925092565b5f60c082019050835182526001600160401b0360208501511660208301526040840151612a95604084018280518252602090810151910152565b5082516080830152602083015160a0830152610ae1565b5f8060408385031215612abd575f80fd5b8235612ac8816125b9565b91506020830135612881816125b9565b5f60608284031215612ae8575f80fd5b610ae183836126d5565b600181811c90821680612b0657607f821691505b60208210810361260757634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156108ad576108ad612b6d565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612bbc575f80fd5b9190910192915050565b5f808335601e19843603018112612bdb575f80fd5b8301803591506001600160401b03821115612bf4575f80fd5b602001915036819003821315612722575f80fd5b5f60208284031215612c18575f80fd5b610ae1826128a3565b601f821115611cde57805f5260205f20601f840160051c81016020851015612c465750805b601f840160051c820191505b81811015611409575f8155600101612c52565b6001600160401b03831115612c7c57612c7c612b24565b612c9083612c8a8354612af2565b83612c21565b5f601f841160018114612cc1575f8515612caa5750838201355b5f19600387901b1c1916600186901b178355611409565b5f83815260208120601f198716915b82811015612cf05786850135825560209485019460019092019101612cd0565b5086821015612d0c575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60208082528181018390525f906040808401600586901b8501820187855b88811015612e1757878303603f190184528135368b9003605e19018112612d89575f80fd5b8a01606063ffffffff612d9b836127ff565b16855261ffff612dac8984016128a3565b168886015286820135601e19833603018112612dc6575f80fd5b9091018781019190356001600160401b03811115612de2575f80fd5b803603831315612df0575f80fd5b8188870152612e028287018285612d1e565b96890196955050509186019150600101612d64565b509098975050505050505050565b5f8085851115612e33575f80fd5b83861115612e3f575f80fd5b5050820193919092039150565b5f8451612e5d81846020890161255a565b8201838582375f930192835250909392505050565b602081525f6110f6602083018486612d1e565b5f823561013e19833603018112612bbc575f80fd5b6001600160401b038116811461154d575f80fd5b63ffffffff612ebc896127ff565b168152602088013560208201525f6040890135612ed881612e9a565b6001600160401b03811660408401525087606083015260e06080830152612f0360e083018789612d1e565b6001600160a01b03861660a084015282810360c0840152612f25818587612d1e565b9a9950505050505050505050565b604080519081016001600160401b0381118282101715612f5557612f55612b24565b60405290565b5f60208284031215612f6b575f80fd5b81516001600160401b0380821115612f81575f80fd5b818401915084601f830112612f94575f80fd5b815181811115612fa657612fa6612b24565b604051601f8201601f19908116603f01168101908382118183101715612fce57612fce612b24565b81604052828152876020848701011115612fe6575f80fd5b611dfa83602083016020880161255a565b5f60408284031215613007575f80fd5b61300f612f33565b82358152602083013560208201528091505092915050565b5f60208284031215613037575f80fd5b8135610ae181612e9a565b60018060a01b038516815283602082015261ffff83166040820152608060608201525f610bfb608083018461257c565b604081525f613084604083018561257c565b8281036020840152611c45818561257c565b5f602082840312156130a6575f80fd5b8151610ae181612831565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a060808401526130e660e084018261257c565b90506060850151603f198483030160a0850152613103828261257c565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f60408284031215613139575f80fd5b613141612f33565b9050815181526020820151602082015292915050565b5f60408284031215613167575f80fd5b610ae18383613129565b6001600160f01b031981358181169160028510156131995780818660020360031b1b83161692505b505092915050565b5f608082840312156131b1575f80fd5b604051606081018181106001600160401b03821117156131d3576131d3612b24565b6040528251815260208301516131e881612e9a565b60208201526131fa8460408501613129565b60408201529392505050565b5f8261322057634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176108ad576108ad612b6d565b803560208310156108ad575f19602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156131995760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201525f82516132c581602c85016020870161255a565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b1660208201528260288201525f825161330781604885016020870161255a565b9190910160480195945050505050565b818103818111156108ad576108ad612b6d565b5f6020828403121561333a575f80fd5b8151610ae1816125b9565b5f8251612bbc81846020870161255a56fea2646970667358221220adddb22f372ce8677d15a9daf6cdcc60363ee043eac004b0cd4669945089b98464736f6c63430008160033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c0000000000000000000000007b1c03eee7adb8f9bb4023ecfa4693fe434e4a80000000000000000000000000000000000000000000000000000000000000000f4865726f6573206f66204d61766961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d41564941000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061025f575f3560e01c80637d25a05e1161013f578063bb0b6a53116100b3578063d045a0dc11610078578063d045a0dc14610759578063d42438851461076c578063dd62ed3e1461078b578063f2fde38b146107cf578063fc0c546a1461047f578063ff7bd03d146107ee575f80fd5b8063bb0b6a53146106bc578063bc70b354146106e7578063bd815db014610706578063c7c7f5b314610719578063ca5eb5e11461073a575f80fd5b80639f68b964116101045780639f68b9641461062e578063a457c2d714610640578063a9059cbb1461065f578063b731ea0a1461067e578063b92d0eff1461047f578063b98bd0701461069d575f80fd5b80637d25a05e1461057f578063857749b0146105b85780638da5cb5b146105cb57806395d89b41146105e7578063963efcaa146105fb575f80fd5b8063313ce567116101d65780635535d4611161019b5780635535d461146104915780635a0dfe4d146104b05780635e280f11146104e55780636fc1b31e1461051857806370a0823114610537578063715018a61461056b575f80fd5b8063313ce567146103f45780633400288b1461041557806339509351146104345780633b6f743b1461045357806352ae28791461047f575f80fd5b8063134d4f2511610227578063134d4f2514610336578063156a0d0f1461035d57806317442b701461038357806318160ddd146103a35780631f5e1334146103c157806323b872dd146103d5575f80fd5b806306fdde0314610263578063095ea7b31461028d5780630d35b415146102bc578063111ecdad146102ea57806313137d6514610321575b5f80fd5b34801561026e575f80fd5b5061027761080d565b60405161028491906125a7565b60405180910390f35b348015610298575f80fd5b506102ac6102a73660046125cd565b61089d565b6040519015158152602001610284565b3480156102c7575f80fd5b506102db6102d636600461260d565b6108b3565b6040516102849392919061263e565b3480156102f5575f80fd5b50600454610309906001600160a01b031681565b6040516001600160a01b039091168152602001610284565b61033461032f366004612729565b61097e565b005b348015610341575f80fd5b5061034a600281565b60405161ffff9091168152602001610284565b348015610368575f80fd5b506040805162b9270b60e21b81526001602082015201610284565b34801561038e575f80fd5b50604080516001808252602082015201610284565b3480156103ae575f80fd5b506007545b604051908152602001610284565b3480156103cc575f80fd5b5061034a600181565b3480156103e0575f80fd5b506102ac6103ef3660046127c1565b610a3e565b3480156103ff575f80fd5b5060125b60405160ff9091168152602001610284565b348015610420575f80fd5b5061033461042f366004612817565b610ae8565b34801561043f575f80fd5b506102ac61044e3660046125cd565b610b66565b34801561045e575f80fd5b5061047261046d36600461283e565b610ba1565b604051610284919061288c565b34801561048a575f80fd5b5030610309565b34801561049c575f80fd5b506102776104ab3660046128b4565b610c05565b3480156104bb575f80fd5b506102ac6104ca366004612817565b63ffffffff919091165f908152600160205260409020541490565b3480156104f0575f80fd5b506103097f0000000000000000000000001a44076050125825900e736c501f859c50fe728c81565b348015610523575f80fd5b506103346105323660046128e5565b610ca7565b348015610542575f80fd5b506103b36105513660046128e5565b6001600160a01b03165f9081526005602052604090205490565b348015610576575f80fd5b50610334610d25565b34801561058a575f80fd5b506105a0610599366004612817565b5f92915050565b6040516001600160401b039091168152602001610284565b3480156105c3575f80fd5b506006610403565b3480156105d6575f80fd5b505f546001600160a01b0316610309565b3480156105f2575f80fd5b50610277610d59565b348015610606575f80fd5b506103b37f000000000000000000000000000000000000000000000000000000e8d4a5100081565b348015610639575f80fd5b505f6102ac565b34801561064b575f80fd5b506102ac61065a3660046125cd565b610d68565b34801561066a575f80fd5b506102ac6106793660046125cd565b610e00565b348015610689575f80fd5b50600254610309906001600160a01b031681565b3480156106a8575f80fd5b506103346106b7366004612940565b610e0c565b3480156106c7575f80fd5b506103b36106d636600461297e565b60016020525f908152604090205481565b3480156106f2575f80fd5b50610277610701366004612997565b610f89565b610334610714366004612940565b6110fe565b61072c6107273660046129f3565b61127e565b604051610284929190612a5b565b348015610745575f80fd5b506103346107543660046128e5565b61136e565b610334610767366004612729565b611410565b348015610777575f80fd5b506103346107863660046128e5565b61143f565b348015610796575f80fd5b506103b36107a5366004612aac565b6001600160a01b039182165f90815260066020908152604080832093909416825291909152205490565b3480156107da575f80fd5b506103346107e93660046128e5565b6114b6565b3480156107f9575f80fd5b506102ac610808366004612ad8565b611550565b60606008805461081c90612af2565b80601f016020809104026020016040519081016040528092919081815260200182805461084890612af2565b80156108935780601f1061086a57610100808354040283529160200191610893565b820191905f5260205f20905b81548152906001019060200180831161087657829003601f168201915b5050505050905090565b5f6108a9338484611584565b5060015b92915050565b604080518082019091525f808252602082015260606108e360405180604001604052805f81526020015f81525090565b6040805180820182525f8082526001600160401b0360208084018290528451838152908101909452919550918261093c565b604080518082019091525f8152606060208201528152602001906001900390816109155790505b5093505f80610960604089013560608a013561095b60208c018c61297e565b6116a7565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031633146109ce576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b602087018035906109e8906109e3908a61297e565b6116ea565b14610a26576109fa602088018861297e565b60405163309afaf360e21b815263ffffffff9091166004820152602088013560248201526044016109c5565b610a3587878787878787611725565b50505050505050565b5f610a4a848484611883565b6001600160a01b0384165f90815260066020908152604080832033845290915290205482811015610ace5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016109c5565b610adb8533858403611584565b60019150505b9392505050565b5f546001600160a01b03163314610b115760405162461bcd60e51b81526004016109c590612b38565b63ffffffff82165f81815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a15050565b335f8181526006602090815260408083206001600160a01b038716845290915281205490916108a9918590610b9c908690612b81565b611584565b604080518082019091525f80825260208201525f610bcf6040850135606086013561095b602088018861297e565b9150505f80610bde8684611a51565b9092509050610bfb610bf3602088018861297e565b838388611b70565b9695505050505050565b600360209081525f928352604080842090915290825290208054610c2890612af2565b80601f0160208091040260200160405190810160405280929190818152602001828054610c5490612af2565b8015610c9f5780601f10610c7657610100808354040283529160200191610c9f565b820191905f5260205f20905b815481529060010190602001808311610c8257829003601f168201915b505050505081565b5f546001600160a01b03163314610cd05760405162461bcd60e51b81526004016109c590612b38565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b5f546001600160a01b03163314610d4e5760405162461bcd60e51b81526004016109c590612b38565b610d575f611c4e565b565b60606009805461081c90612af2565b335f9081526006602090815260408083206001600160a01b038616845290915281205482811015610de95760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016109c5565b610df63385858403611584565b5060019392505050565b5f6108a9338484611883565b5f546001600160a01b03163314610e355760405162461bcd60e51b81526004016109c590612b38565b5f5b81811015610f5757610e79838383818110610e5457610e54612b94565b9050602002810190610e669190612ba8565b610e74906040810190612bc6565b611c9d565b828282818110610e8b57610e8b612b94565b9050602002810190610e9d9190612ba8565b610eab906040810190612bc6565b60035f868686818110610ec057610ec0612b94565b9050602002810190610ed29190612ba8565b610ee090602081019061297e565b63ffffffff1663ffffffff1681526020019081526020015f205f868686818110610f0c57610f0c612b94565b9050602002810190610f1e9190612ba8565b610f2f906040810190602001612c08565b61ffff16815260208101919091526040015f2091610f4e919083612c65565b50600101610e37565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6748282604051610b5a929190612d46565b63ffffffff84165f90815260036020908152604080832061ffff87168452909152812080546060929190610fbc90612af2565b80601f0160208091040260200160405190810160405280929190818152602001828054610fe890612af2565b80156110335780601f1061100a57610100808354040283529160200191611033565b820191905f5260205f20905b81548152906001019060200180831161101657829003601f168201915b5050505050905080515f036110815783838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509294506110f69350505050565b5f8390036110905790506110f6565b600283106110d9576110a28484611c9d565b806110b08460028188612e25565b6040516020016110c293929190612e4c565b6040516020818303038152906040529150506110f6565b8383604051639a6d49cd60e01b81526004016109c5929190612e72565b949350505050565b5f5b81811015611201573683838381811061111b5761111b612b94565b905060200281019061112d9190612e85565b905061115f61113f602083018361297e565b602083013563ffffffff919091165f908152600160205260409020541490565b61116957506111f9565b3063d045a0dc60c08301358360a0810135611188610100830183612bc6565b611199610100890160e08a016128e5565b6111a76101208a018a612bc6565b6040518963ffffffff1660e01b81526004016111c99796959493929190612eae565b5f604051808303818588803b1580156111e0575f80fd5b505af11580156111f2573d5f803e3d5ffd5b5050505050505b600101611100565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b81526004015f60405180830381865afa15801561123d573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112649190810190612f5b565b604051638351eea760e01b81526004016109c591906125a7565b611286612517565b604080518082019091525f80825260208201525f806112ba604088013560608901356112b560208b018b61297e565b611ce3565b915091505f806112ca8984611a51565b90925090506112f66112df60208b018b61297e565b83836112f0368d90038d018d612ff7565b8b611cff565b60408051808201909152858152602080820186905282519298509096503391907ffff873bb909b73d08a8c1af4b21779e87103bb8ea8cf3b3a0067eb8526b8b80a90611344908d018d61297e565b6040805163ffffffff9092168252602082018990520160405180910390a350505050935093915050565b5f546001600160a01b031633146113975760405162461bcd60e51b81526004016109c590612b38565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c169063ca5eb5e1906024015f604051808303815f87803b1580156113f7575f80fd5b505af1158015611409573d5f803e3d5ffd5b5050505050565b3330146114305760405163029a949d60e31b815260040160405180910390fd5b610a3587878787878787610a26565b5f546001600160a01b031633146114685760405162461bcd60e51b81526004016109c590612b38565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610d1a565b5f546001600160a01b031633146114df5760405162461bcd60e51b81526004016109c590612b38565b6001600160a01b0381166115445760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109c5565b61154d81611c4e565b50565b5f602082018035906001908390611567908661297e565b63ffffffff16815260208101919091526040015f20541492915050565b6001600160a01b0383166115e65760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016109c5565b6001600160a01b0382166116475760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016109c5565b6001600160a01b038381165f8181526006602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f806116b285611e05565b9150819050838110156116e2576040516371c4efed60e01b815260048101829052602481018590526044016109c5565b935093915050565b63ffffffff81165f90815260016020526040812054806108ad5760405163f6ff4fb760e01b815263ffffffff841660048201526024016109c5565b5f6117366117338787611e3b565b90565b90505f6117618261174f61174a8a8a611e52565b611e74565b61175c60208d018d61297e565b611ea8565b90506028861115611821575f61179d61178060608c0160408d01613027565b61178d60208d018d61297e565b846117988c8c611ebb565b611f05565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000001a44076050125825900e736c501f859c50fe728c1690637cb59012906117f29086908d905f908790600401613042565b5f604051808303815f87803b158015611809575f80fd5b505af115801561181b573d5f803e3d5ffd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61185a60208d018d61297e565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383166118e75760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016109c5565b6001600160a01b0382166119495760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016109c5565b6001600160a01b0383165f90815260056020526040902054818110156119c05760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016109c5565b6001600160a01b038085165f908152600560205260408082208585039055918516815290812080548492906119f6908490612b81565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a4291815260200190565b60405180910390a35b50505050565b6060805f611aac8560200135611a6686611f37565b611a7360a0890189612bc6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f6292505050565b90935090505f81611abe576001611ac1565b60025b9050611ae1611ad3602088018861297e565b8261070160808a018a612bc6565b6004549093506001600160a01b031615611b67576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb91611b26918891889101613072565b602060405180830381865afa158015611b41573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b659190613096565b505b50509250929050565b604080518082019091525f80825260208201527f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611bd2896116ea565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611c079291906130b1565b6040805180830381865afa158015611c21573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c459190613157565b95945050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f611cab6002828486612e25565b611cb491613171565b60f01c905060038114611cde578282604051639a6d49cd60e01b81526004016109c5929190612e72565b505050565b5f80611cf08585856116a7565b90925090506116e23383611fdc565b611d07612517565b5f611d14845f0151612127565b602085015190915015611d2e57611d2e846020015161214e565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611d7e8c6116ea565b81526020018a81526020018981526020015f8960200151111515815250866040518463ffffffff1660e01b8152600401611db99291906130b1565b60806040518083038185885af1158015611dd5573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190611dfa91906131a1565b979650505050505050565b5f7f000000000000000000000000000000000000000000000000000000e8d4a51000611e318184613206565b6108ad9190613225565b5f611e496020828486612e25565b610ae19161323c565b5f611e61602860208486612e25565b611e6a91613259565b60c01c9392505050565b5f6108ad7f000000000000000000000000000000000000000000000000000000e8d4a510006001600160401b038416613225565b5f611eb38484612231565b509092915050565b6060611eca8260288186612e25565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929695505050505050565b606084848484604051602001611f1e9493929190613287565b6040516020818303038152906040529050949350505050565b5f6108ad7f000000000000000000000000000000000000000000000000000000e8d4a5100083613206565b8051606090151580611fab578484604051602001611f9792919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052611fd2565b84843385604051602001611fc294939291906132d5565b6040516020818303038152906040525b9150935093915050565b6001600160a01b03821661203c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016109c5565b6001600160a01b0382165f90815260056020526040902054818110156120af5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016109c5565b6001600160a01b0383165f9081526005602052604081208383039055600780548492906120dd908490613317565b90915550506040518281525f906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b5f81341461214a576040516304fb820960e51b81523460048201526024016109c5565b5090565b5f7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121cf919061332a565b90506001600160a01b0381166121f8576040516329b99a9560e11b815260040160405180910390fd5b61222d6001600160a01b038216337f0000000000000000000000001a44076050125825900e736c501f859c50fe728c8561230d565b5050565b6001600160a01b0382166122875760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016109c5565b8060075f8282546122989190612b81565b90915550506001600160a01b0382165f90815260056020526040812080548392906122c4908490612b81565b90915550506040518181526001600160a01b038316905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180516001600160e01b03166323b872dd60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152611a4b928792915f916123a4918516908490612421565b805190915015611cde57808060200190518101906123c29190613096565b611cde5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109c5565b60606110f684845f8585843b6124795760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109c5565b5f80866001600160a01b031685876040516124949190613345565b5f6040518083038185875af1925050503d805f81146124ce576040519150601f19603f3d011682016040523d82523d5f602084013e6124d3565b606091505b5091509150611dfa828286606083156124ed575081610ae1565b8251156124fd5782518084602001fd5b8160405162461bcd60e51b81526004016109c591906125a7565b60405180606001604052805f80191681526020015f6001600160401b0316815260200161255560405180604001604052805f81526020015f81525090565b905290565b5f5b8381101561257457818101518382015260200161255c565b50505f910152565b5f815180845261259381602086016020860161255a565b601f01601f19169290920160200192915050565b602081525f610ae1602083018461257c565b6001600160a01b038116811461154d575f80fd5b5f80604083850312156125de575f80fd5b82356125e9816125b9565b946020939093013593505050565b5f60e08284031215612607575f80fd5b50919050565b5f6020828403121561261d575f80fd5b81356001600160401b03811115612632575f80fd5b6110f6848285016125f7565b83518152602080850151908201525f60a08201604060a0604085015281865180845260c08601915060c08160051b870101935060208089015f5b838110156126b75788870360bf190185528151805188528301518388018790526126a48789018261257c565b9750509382019390820190600101612678565b505087516060880152505050602085015160808501525090506110f6565b5f60608284031215612607575f80fd5b5f8083601f8401126126f5575f80fd5b5081356001600160401b0381111561270b575f80fd5b602083019150836020828501011115612722575f80fd5b9250929050565b5f805f805f805f60e0888a03121561273f575f80fd5b61274989896126d5565b96506060880135955060808801356001600160401b038082111561276b575f80fd5b6127778b838c016126e5565b909750955060a08a0135915061278c826125b9565b90935060c089013590808211156127a1575f80fd5b506127ae8a828b016126e5565b989b979a50959850939692959293505050565b5f805f606084860312156127d3575f80fd5b83356127de816125b9565b925060208401356127ee816125b9565b929592945050506040919091013590565b803563ffffffff81168114612812575f80fd5b919050565b5f8060408385031215612828575f80fd5b6125e9836127ff565b801515811461154d575f80fd5b5f806040838503121561284f575f80fd5b82356001600160401b03811115612864575f80fd5b612870858286016125f7565b925050602083013561288181612831565b809150509250929050565b8151815260208083015190820152604081016108ad565b803561ffff81168114612812575f80fd5b5f80604083850312156128c5575f80fd5b6128ce836127ff565b91506128dc602084016128a3565b90509250929050565b5f602082840312156128f5575f80fd5b8135610ae1816125b9565b5f8083601f840112612910575f80fd5b5081356001600160401b03811115612926575f80fd5b6020830191508360208260051b8501011115612722575f80fd5b5f8060208385031215612951575f80fd5b82356001600160401b03811115612966575f80fd5b61297285828601612900565b90969095509350505050565b5f6020828403121561298e575f80fd5b610ae1826127ff565b5f805f80606085870312156129aa575f80fd5b6129b3856127ff565b93506129c1602086016128a3565b925060408501356001600160401b038111156129db575f80fd5b6129e7878288016126e5565b95989497509550505050565b5f805f8385036080811215612a06575f80fd5b84356001600160401b03811115612a1b575f80fd5b612a27878288016125f7565b9450506040601f1982011215612a3b575f80fd5b506020840191506060840135612a50816125b9565b809150509250925092565b5f60c082019050835182526001600160401b0360208501511660208301526040840151612a95604084018280518252602090810151910152565b5082516080830152602083015160a0830152610ae1565b5f8060408385031215612abd575f80fd5b8235612ac8816125b9565b91506020830135612881816125b9565b5f60608284031215612ae8575f80fd5b610ae183836126d5565b600181811c90821680612b0657607f821691505b60208210810361260757634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b808201808211156108ad576108ad612b6d565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112612bbc575f80fd5b9190910192915050565b5f808335601e19843603018112612bdb575f80fd5b8301803591506001600160401b03821115612bf4575f80fd5b602001915036819003821315612722575f80fd5b5f60208284031215612c18575f80fd5b610ae1826128a3565b601f821115611cde57805f5260205f20601f840160051c81016020851015612c465750805b601f840160051c820191505b81811015611409575f8155600101612c52565b6001600160401b03831115612c7c57612c7c612b24565b612c9083612c8a8354612af2565b83612c21565b5f601f841160018114612cc1575f8515612caa5750838201355b5f19600387901b1c1916600186901b178355611409565b5f83815260208120601f198716915b82811015612cf05786850135825560209485019460019092019101612cd0565b5086821015612d0c575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60208082528181018390525f906040808401600586901b8501820187855b88811015612e1757878303603f190184528135368b9003605e19018112612d89575f80fd5b8a01606063ffffffff612d9b836127ff565b16855261ffff612dac8984016128a3565b168886015286820135601e19833603018112612dc6575f80fd5b9091018781019190356001600160401b03811115612de2575f80fd5b803603831315612df0575f80fd5b8188870152612e028287018285612d1e565b96890196955050509186019150600101612d64565b509098975050505050505050565b5f8085851115612e33575f80fd5b83861115612e3f575f80fd5b5050820193919092039150565b5f8451612e5d81846020890161255a565b8201838582375f930192835250909392505050565b602081525f6110f6602083018486612d1e565b5f823561013e19833603018112612bbc575f80fd5b6001600160401b038116811461154d575f80fd5b63ffffffff612ebc896127ff565b168152602088013560208201525f6040890135612ed881612e9a565b6001600160401b03811660408401525087606083015260e06080830152612f0360e083018789612d1e565b6001600160a01b03861660a084015282810360c0840152612f25818587612d1e565b9a9950505050505050505050565b604080519081016001600160401b0381118282101715612f5557612f55612b24565b60405290565b5f60208284031215612f6b575f80fd5b81516001600160401b0380821115612f81575f80fd5b818401915084601f830112612f94575f80fd5b815181811115612fa657612fa6612b24565b604051601f8201601f19908116603f01168101908382118183101715612fce57612fce612b24565b81604052828152876020848701011115612fe6575f80fd5b611dfa83602083016020880161255a565b5f60408284031215613007575f80fd5b61300f612f33565b82358152602083013560208201528091505092915050565b5f60208284031215613037575f80fd5b8135610ae181612e9a565b60018060a01b038516815283602082015261ffff83166040820152608060608201525f610bfb608083018461257c565b604081525f613084604083018561257c565b8281036020840152611c45818561257c565b5f602082840312156130a6575f80fd5b8151610ae181612831565b6040815263ffffffff8351166040820152602083015160608201525f604084015160a060808401526130e660e084018261257c565b90506060850151603f198483030160a0850152613103828261257c565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b5f60408284031215613139575f80fd5b613141612f33565b9050815181526020820151602082015292915050565b5f60408284031215613167575f80fd5b610ae18383613129565b6001600160f01b031981358181169160028510156131995780818660020360031b1b83161692505b505092915050565b5f608082840312156131b1575f80fd5b604051606081018181106001600160401b03821117156131d3576131d3612b24565b6040528251815260208301516131e881612e9a565b60208201526131fa8460408501613129565b60408201529392505050565b5f8261322057634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176108ad576108ad612b6d565b803560208310156108ad575f19602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156131995760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201525f82516132c581602c85016020870161255a565b91909101602c0195945050505050565b8481526001600160401b0360c01b8460c01b1660208201528260288201525f825161330781604885016020870161255a565b9190910160480195945050505050565b818103818111156108ad576108ad612b6d565b5f6020828403121561333a575f80fd5b8151610ae1816125b9565b5f8251612bbc81846020870161255a56fea2646970667358221220adddb22f372ce8677d15a9daf6cdcc60363ee043eac004b0cd4669945089b98464736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000001a44076050125825900e736c501f859c50fe728c0000000000000000000000007b1c03eee7adb8f9bb4023ecfa4693fe434e4a80000000000000000000000000000000000000000000000000000000000000000f4865726f6573206f66204d61766961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d41564941000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Heroes of Mavia
Arg [1] : _symbol (string): MAVIA
Arg [2] : _layerZeroEndpoint (address): 0x1a44076050125825900e736c501f859c50fE728c
Arg [3] : _owner (address): 0x7b1c03EEE7aDB8F9BB4023ecfa4693fE434E4a80
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [3] : 0000000000000000000000007b1c03eee7adb8f9bb4023ecfa4693fe434e4a80
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000f
Arg [5] : 4865726f6573206f66204d617669610000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [7] : 4d41564941000000000000000000000000000000000000000000000000000000
Deployed ByteCode Sourcemap
190:378:36:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2084:98:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4181:166;;;;;;;;;;-1:-1:-1;4181:166:29;;;;;:::i;:::-;;:::i;:::-;;;1391:14:37;;1384:22;1366:41;;1354:2;1339:18;4181:166:29;1226:187:37;4273:1258:10;;;;;;;;;;-1:-1:-1;4273:1258:10;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2132:27::-;;;;;;;;;;-1:-1:-1;2132:27:10;;;;-1:-1:-1;;;;;2132:27:10;;;;;;-1:-1:-1;;;;;3605:32:37;;;3587:51;;3575:2;3560:18;2132:27:10;3441:203:37;3974:708:2;;;;;;:::i;:::-;;:::i;:::-;;2006:40:10;;;;;;;;;;;;2045:1;2006:40;;;;;5387:6:37;5375:19;;;5357:38;;5345:2;5330:18;2006:40:10;5213:188:37;1364:140:9;;;;;;;;;;-1:-1:-1;1364:140:9;;;-1:-1:-1;;;5576:52:37;;1495:1:9;5659:2:37;5644:18;;5637:59;5549:18;1364:140:9;5406:296:37;1287:235:0;;;;;;;;;;-1:-1:-1;1287:235:0;;;843:1:3;5914:34:37;;;5979:2;5964:18;;5957:43;5850:18;1287:235:0;5707:299:37;3172:106:29;;;;;;;;;;-1:-1:-1;3259:12:29;;3172:106;;;6157:25:37;;;6145:2;6130:18;3172:106:29;6011:177:37;1969:31:10;;;;;;;;;;;;1999:1;1969:31;;4814:478:29;;;;;;;;;;-1:-1:-1;4814:478:29;;;;;:::i;:::-;;:::i;3021:91::-;;;;;;;;;;-1:-1:-1;3103:2:29;3021:91;;;6826:4:37;6814:17;;;6796:36;;6784:2;6769:18;3021:91:29;6654:184:37;1724:141:1;;;;;;;;;;-1:-1:-1;1724:141:1;;;;;:::i;:::-;;:::i;5687:212:29:-;;;;;;;;;;-1:-1:-1;5687:212:29;;;;;:::i;:::-;;:::i;5982:774:10:-;;;;;;;;;;-1:-1:-1;5982:774:10;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;875:93:14:-;;;;;;;;;;-1:-1:-1;956:4:14;875:93;;538::8;;;;;;;;;;-1:-1:-1;538:93:8;;;;;:::i;:::-;;:::i;14078:132:10:-;;;;;;;;;;-1:-1:-1;14078:132:10;;;;;:::i;:::-;14183:11;;;;;14160:4;14183:11;;;:5;:11;;;;;;:20;;14078:132;446:46:1;;;;;;;;;;;;;;;3804:163:10;;;;;;;;;;-1:-1:-1;3804:163:10;;;;;:::i;:::-;;:::i;3336:125:29:-;;;;;;;;;;-1:-1:-1;3336:125:29;;;;;:::i;:::-;-1:-1:-1;;;;;3436:18:29;3410:7;3436:18;;;:9;:18;;;;;;;3336:125;1605:92:28;;;;;;;;;;;;;:::i;3113:128:2:-;;;;;;;;;;-1:-1:-1;3113:128:2;;;;;:::i;:::-;3202:12;3113:128;;;;;;;;-1:-1:-1;;;;;9446:31:37;;;9428:50;;9416:2;9401:18;3113:128:2;9284:200:37;3369:87:10;;;;;;;;;;-1:-1:-1;3448:1:10;3369:87;;973:85:28;;;;;;;;;;-1:-1:-1;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;973:85;;2295:102:29;;;;;;;;;;;;;:::i;1663:46:10:-;;;;;;;;;;;;;;;2117:94:9;;;;;;;;;;-1:-1:-1;2176:4:9;2117:94;;6386:405:29;;;;;;;;;;-1:-1:-1;6386:405:29;;;;;:::i;:::-;;:::i;3664:172::-;;;;;;;;;;-1:-1:-1;3664:172:29;;;;;:::i;:::-;;:::i;559:23:14:-;;;;;;;;;;-1:-1:-1;559:23:14;;;;-1:-1:-1;;;;;559:23:14;;;1391:523:8;;;;;;;;;;-1:-1:-1;1391:523:8;;;;;:::i;:::-;;:::i;569:48:1:-;;;;;;;;;;-1:-1:-1;569:48:1;;;;;:::i;:::-;;;;;;;;;;;;;;2673:981:8;;;;;;;;;;-1:-1:-1;2673:981:8;;;;;:::i;:::-;;:::i;1698:1333:14:-;;;;;;:::i;:::-;;:::i;7444:1281:10:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;2697:105:1:-;;;;;;;;;;-1:-1:-1;2697:105:1;;;;;:::i;:::-;;:::i;3679:409:14:-;;;;;;:::i;:::-;;:::i;1100:139::-;;;;;;;;;;-1:-1:-1;1100:139:14;;;;;:::i;:::-;;:::i;3894:149:29:-;;;;;;;;;;-1:-1:-1;3894:149:29;;;;;:::i;:::-;-1:-1:-1;;;;;4009:18:29;;;3983:7;4009:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3894:149;1846:189:28;;;;;;;;;;-1:-1:-1;1846:189:28;;;;;:::i;:::-;;:::i;2377:149:2:-;;;;;;;;;;-1:-1:-1;2377:149:2;;;;;:::i;:::-;;:::i;2084:98:29:-;2138:13;2170:5;2163:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2084:98;:::o;4181:166::-;4264:4;4280:39;666:10:34;4303:7:29;4312:6;4280:8;:39::i;:::-;-1:-1:-1;4336:4:29;4181:166;;;;;:::o;4273:1258:10:-;-1:-1:-1;;;;;;;;;;;;;;;;;4425:35:10;4462:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;4462:28:10;4680:34;;;;;;;;-1:-1:-1;4680:34:10;;;-1:-1:-1;;;;;4680:34:10;;;;;;;4831:21;;;;;;;;;;;4680:34;;-1:-1:-1;;;4831:21:10;;;-1:-1:-1;;;;;;;;;;;;;;;;;4831:21:10;;;;;;;;;;;;;;;-1:-1:-1;4815:37:10;-1:-1:-1;5289:20:10;;5339:120;5363:19;;;;5396:22;;;;5432:17;;;;5363:10;5432:17;:::i;:::-;5339:10;:120::i;:::-;5482:42;;;;;;;;;;;;;;;;4273:1258;;;;-1:-1:-1;;;;;;4273:1258:10:o;3974:708:2:-;4287:8;-1:-1:-1;;;;;4279:31:2;4300:10;4279:31;4275:68;;4319:24;;-1:-1:-1;;;4319:24:2;;4332:10;4319:24;;;3587:51:37;3560:18;;4319:24:2;;;;;;;;4275:68;4479:14;;;;;;4443:32;;4460:14;;4479:7;4460:14;:::i;:::-;4443:16;:32::i;:::-;:50;4439:103;;4511:14;;;;:7;:14;:::i;:::-;4502:40;;-1:-1:-1;;;4502:40:2;;14462:10:37;14450:23;;;4502:40:2;;;14432:42:37;4527:14:2;;;;14490:18:37;;;14483:34;14405:18;;4502:40:2;14260:263:37;4439:103:2;4616:59;4627:7;4636:5;4643:8;;4653:9;4664:10;;4616;:59::i;:::-;3974:708;;;;;;;:::o;4814:478:29:-;4950:4;4966:36;4976:6;4984:9;4995:6;4966:9;:36::i;:::-;-1:-1:-1;;;;;5040:19:29;;5013:24;5040:19;;;:11;:19;;;;;;;;666:10:34;5040:33:29;;;;;;;;5091:26;;;;5083:79;;;;-1:-1:-1;;;5083:79:29;;14730:2:37;5083:79:29;;;14712:21:37;14769:2;14749:18;;;14742:30;14808:34;14788:18;;;14781:62;-1:-1:-1;;;14859:18:37;;;14852:38;14907:19;;5083:79:29;14528:404:37;5083:79:29;5196:57;5205:6;666:10:34;5246:6:29;5227:16;:25;5196:8;:57::i;:::-;5281:4;5274:11;;;4814:478;;;;;;:::o;1724:141:1:-;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;1804:11:1::1;::::0;::::1;;::::0;;;:5:::1;:11;::::0;;;;;;;;:19;;;1838:20;;14432:42:37;;;14490:18;;14483:34;;;1838:20:1::1;::::0;14405:18:37;1838:20:1::1;;;;;;;;1724:141:::0;;:::o;5687:212:29:-;666:10:34;5775:4:29;5823:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;5823:34:29;;;;;;;;;;5775:4;;5791:80;;5814:7;;5823:47;;5860:10;;5823:47;:::i;:::-;5791:8;:80::i;5982:774:10:-;-1:-1:-1;;;;;;;;;;;;;;;;;6316:24:10;6344:74;6355:19;;;;6376:22;;;;6400:17;;;;6355:10;6400:17;:::i;6344:74::-;6313:105;;;6507:20;6529;6553:49;6573:10;6585:16;6553:19;:49::i;:::-;6506:96;;-1:-1:-1;6506:96:10;-1:-1:-1;6691:58:10;6698:17;;;;:10;:17;:::i;:::-;6717:7;6726;6735:13;6691:6;:58::i;:::-;6684:65;5982:774;-1:-1:-1;;;;;;5982:774:10:o;538:93:8:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3804:163:10:-;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;3887:12:10::1;:28:::0;;-1:-1:-1;;;;;;3887:28:10::1;-1:-1:-1::0;;;;;3887:28:10;::::1;::::0;;::::1;::::0;;;3930:30:::1;::::0;3587:51:37;;;3930:30:10::1;::::0;3575:2:37;3560:18;3930:30:10::1;;;;;;;;3804:163:::0;:::o;1605:92:28:-;1019:7;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;1669:21:::1;1687:1;1669:9;:21::i;:::-;1605:92::o:0;2295:102:29:-;2351:13;2383:7;2376:14;;;;;:::i;6386:405::-;666:10:34;6479:4:29;6522:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;6522:34:29;;;;;;;;;;6574:35;;;;6566:85;;;;-1:-1:-1;;;6566:85:29;;15762:2:37;6566:85:29;;;15744:21:37;15801:2;15781:18;;;15774:30;15840:34;15820:18;;;15813:62;-1:-1:-1;;;15891:18:37;;;15884:35;15936:19;;6566:85:29;15560:401:37;6566:85:29;6685:67;666:10:34;6708:7:29;6736:15;6717:16;:34;6685:8;:67::i;:::-;-1:-1:-1;6780:4:29;;6386:405;-1:-1:-1;;;6386:405:29:o;3664:172::-;3750:4;3766:42;666:10:34;3790:9:29;3801:6;3766:9;:42::i;1391:523:8:-;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;1508:9:8::1;1503:354;1523:27:::0;;::::1;1503:354;;;1685:48;1705:16;;1722:1;1705:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;1685:19;:48::i;:::-;1819:16;;1836:1;1819:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;1747:15;:40;1763:16;;1780:1;1763:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:23;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;1747:40;;;;;;;;;;;;;;;:69;1788:16;;1805:1;1788:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;;;;;::::1;;;:::i;:::-;1747:69;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;1747:69:8;;:99:::1;::::0;;:69;:99:::1;:::i;:::-;-1:-1:-1::0;1552:3:8::1;;1503:354;;;;1872:35;1890:16;;1872:35;;;;;;;:::i;2673:981::-:0;2864:21;;;2840;2864;;;:15;:21;;;;;;;;:31;;;;;;;;;;2840:55;;2816:12;;2840:21;2864:31;2840:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3024:8;:15;3043:1;3024:20;3020:46;;3053:13;;3046:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3046:20:8;;-1:-1:-1;3046:20:8;;-1:-1:-1;;;;3046:20:8;3020:46;3151:1;3127:25;;;3123:46;;3161:8;-1:-1:-1;3154:15:8;;3123:46;3316:1;3292:25;;3288:267;;3333:34;3353:13;;3333:19;:34::i;:::-;3516:8;3526:17;:13;3540:1;3526:13;;:17;:::i;:::-;3503:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;3496:48;;;;;3288:267;3633:13;;3618:29;;-1:-1:-1;;;3618:29:8;;;;;;;;;:::i;2673:981::-;;;;;;;:::o;1698:1333:14:-;1799:9;1794:1037;1814:19;;;1794:1037;;;1854:29;1886:8;;1895:1;1886:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;1854:43;-1:-1:-1;1980:50:14;1987:20;;;;1854:43;1987:20;:::i;:::-;2009;;;;14183:11:10;;;;;14160:4;14183:11;;;:5;:11;;;;;;:20;;14078:132;1980:50:14;1975:65;;2032:8;;;1975:65;2602:4;:22;2633:12;;;;:6;2696:11;;;;2725:14;;;;2633:6;2725:14;:::i;:::-;2757:15;;;;;;;;:::i;:::-;2790:16;;;;:6;:16;:::i;:::-;2602:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1840:991;1794:1037;1835:3;;1794:1037;;;;2988:10;-1:-1:-1;;;;;2978:43:14;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2978:45:14;;;;;;;;;;;;:::i;:::-;2961:63;;-1:-1:-1;;;2961:63:14;;;;;;;;:::i;7444:1281:10:-;7605:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;7986:20:10;;8036:116;8056:19;;;;8089:22;;;;8125:17;;;;8056:10;8125:17;:::i;:::-;8036:6;:116::i;:::-;7985:167;;;;8241:20;8263;8287:49;8307:10;8319:16;8287:19;:49::i;:::-;8240:96;;-1:-1:-1;8240:96:10;-1:-1:-1;8459:66:10;8467:17;;;;:10;:17;:::i;:::-;8486:7;8495;8459:66;;;;;;;8504:4;8459:66;:::i;:::-;8510:14;8459:7;:66::i;:::-;8591:42;;;;;;;;;;;;;;;;;;;8657:15;;8446:79;;-1:-1:-1;8591:42:10;;-1:-1:-1;8693:10:10;;8657:15;8649:69;;8674:17;;;;:10;:17;:::i;:::-;8649:69;;;14462:10:37;14450:23;;;14432:42;;14505:2;14490:18;;14483:34;;;14405:18;8649:69:10;;;;;;;7671:1054;;;;7444:1281;;;;;;:::o;2697:105:1:-;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;2764:31:1::1;::::0;-1:-1:-1;;;2764:31:1;;-1:-1:-1;;;;;3605:32:37;;;2764:31:1::1;::::0;::::1;3587:51:37::0;2764:8:1::1;:20;::::0;::::1;::::0;3560:18:37;;2764:31:1::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;2697:105:::0;:::o;3679:409:14:-;3958:10;3980:4;3958:27;3954:50;;3994:10;;-1:-1:-1;;;3994:10:14;;;;;;;;;;;3954:50;4014:67;4033:7;4042:5;4049:8;;4059:9;4070:10;;4014:18;:67::i;1100:139::-;1019:7:28;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;1175:8:14::1;:20:::0;;-1:-1:-1;;;;;;1175:20:14::1;-1:-1:-1::0;;;;;1175:20:14;::::1;::::0;;::::1;::::0;;;1210:22:::1;::::0;3587:51:37;;;1210:22:14::1;::::0;3575:2:37;3560:18;1210:22:14::1;3441:203:37::0;1846:189:28;1019:7;1045:6;-1:-1:-1;;;;;1045:6:28;666:10:34;1185:23:28;1177:68;;;;-1:-1:-1;;;1177:68:28;;;;;;;:::i;:::-;-1:-1:-1;;;;;1934:22:28;::::1;1926:73;;;::::0;-1:-1:-1;;;1926:73:28;;25721:2:37;1926:73:28::1;::::0;::::1;25703:21:37::0;25760:2;25740:18;;;25733:30;25799:34;25779:18;;;25772:62;-1:-1:-1;;;25850:18:37;;;25843:36;25896:19;;1926:73:28::1;25519:402:37::0;1926:73:28::1;2009:19;2019:8;2009:9;:19::i;:::-;1846:189:::0;:::o;2377:149:2:-;2459:4;2506:13;;;;;;2482:5;;2459:4;;2488:13;;2506:6;2488:13;:::i;:::-;2482:20;;;;;;;;;;;;;-1:-1:-1;2482:20:2;;:37;;2377:149;-1:-1:-1;;2377:149:2:o;9962:370:29:-;-1:-1:-1;;;;;10093:19:29;;10085:68;;;;-1:-1:-1;;;10085:68:29;;26128:2:37;10085:68:29;;;26110:21:37;26167:2;26147:18;;;26140:30;26206:34;26186:18;;;26179:62;-1:-1:-1;;;26257:18:37;;;26250:34;26301:19;;10085:68:29;25926:400:37;10085:68:29;-1:-1:-1;;;;;10171:21:29;;10163:68;;;;-1:-1:-1;;;10163:68:29;;26533:2:37;10163:68:29;;;26515:21:37;26572:2;26552:18;;;26545:30;26611:34;26591:18;;;26584:62;-1:-1:-1;;;26662:18:37;;;26655:32;26704:19;;10163:68:29;26331:398:37;10163:68:29;-1:-1:-1;;;;;10242:18:29;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10293:32;;6157:25:37;;;10293:32:29;;6130:18:37;10293:32:29;;;;;;;9962:370;;;:::o;16095:668:10:-;16237:20;16259:24;16433:22;16445:9;16433:11;:22::i;:::-;16418:37;;16581:12;16562:31;;16663:12;16644:16;:31;16640:117;;;16698:48;;-1:-1:-1;;;16698:48:10;;;;;26908:25:37;;;26949:18;;;26942:34;;;26881:18;;16698:48:10;26734:248:37;16640:117:10;16095:668;;;;;;:::o;2163:196:1:-;2267:11;;;2233:7;2267:11;;;:5;:11;;;;;;;2288:43;;2319:12;;-1:-1:-1;;;2319:12:1;;27161:10:37;27149:23;;2319:12:1;;;27131:42:37;27104:18;;2319:12:1;26987:192:37;10871:1806:10;11348:17;11368:36;:17;:8;;:15;:17::i;:::-;2891:2:13;2780:123;11368:36:10;11348:56;;11537:24;11564:62;11572:9;11583:26;11589:19;:8;;:17;:19::i;:::-;11583:5;:26::i;:::-;11611:14;;;;:7;:14;:::i;:::-;11564:7;:62::i;:::-;11537:89;-1:-1:-1;243:2:13;-1:-1:-1;;11637:955:10;;;11741:23;11767:175;11810:13;;;;;;;;:::i;:::-;11841:14;;;;:7;:14;:::i;:::-;11873:16;11907:21;:8;;:19;:21::i;:::-;11767:25;:175::i;:::-;12489:92;;-1:-1:-1;;;12489:92:10;;11741:201;;-1:-1:-1;;;;;;12489:8:10;:20;;;;:92;;12510:9;;12521:5;;12528:1;;11741:201;;12489:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11664:928;11637:955;-1:-1:-1;;;;;12607:63:10;;12619:5;12607:63;12626:14;;;;:7;:14;:::i;:::-;12607:63;;;14462:10:37;14450:23;;;14432:42;;14505:2;14490:18;;14483:34;;;14405:18;12607:63:10;;;;;;;11174:1503;;10871:1806;;;;;;;:::o;7265:713:29:-;-1:-1:-1;;;;;7400:20:29;;7392:70;;;;-1:-1:-1;;;7392:70:29;;28120:2:37;7392:70:29;;;28102:21:37;28159:2;28139:18;;;28132:30;28198:34;28178:18;;;28171:62;-1:-1:-1;;;28249:18:37;;;28242:35;28294:19;;7392:70:29;27918:401:37;7392:70:29;-1:-1:-1;;;;;7480:23:29;;7472:71;;;;-1:-1:-1;;;7472:71:29;;28526:2:37;7472:71:29;;;28508:21:37;28565:2;28545:18;;;28538:30;28604:34;28584:18;;;28577:62;-1:-1:-1;;;28655:18:37;;;28648:33;28698:19;;7472:71:29;28324:399:37;7472:71:29;-1:-1:-1;;;;;7636:17:29;;7612:21;7636:17;;;:9;:17;;;;;;7671:23;;;;7663:74;;;;-1:-1:-1;;;7663:74:29;;28930:2:37;7663:74:29;;;28912:21:37;28969:2;28949:18;;;28942:30;29008:34;28988:18;;;28981:62;-1:-1:-1;;;29059:18:37;;;29052:36;29105:19;;7663:74:29;28728:402:37;7663:74:29;-1:-1:-1;;;;;7771:17:29;;;;;;;:9;:17;;;;;;7791:22;;;7771:42;;7833:20;;;;;;;;:30;;7807:6;;7771:17;7833:30;;7807:6;;7833:30;:::i;:::-;;;;;;;;7896:9;-1:-1:-1;;;;;7879:35:29;7888:6;-1:-1:-1;;;;;7879:35:29;;7907:6;7879:35;;;;6157:25:37;;6145:2;6130:18;;6011:177;7879:35:29;;;;;;;;7925:46;7382:596;7265:713;;;:::o;9019:1334:10:-;9151:20;9173;9205:15;9376:324;9408:10;:13;;;9435:16;9441:9;9435:5;:16::i;:::-;9669:21;;;;:10;:21;:::i;:::-;9376:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9376:18:10;;-1:-1:-1;;;9376:324:10:i;:::-;9352:348;;-1:-1:-1;9352:348:10;-1:-1:-1;9780:14:10;9352:348;9797:33;;1999:1;9797:33;;;2045:1;9797:33;9780:50;-1:-1:-1;9952:67:10;9967:17;;;;:10;:17;:::i;:::-;9986:7;9995:23;;;;:10;:23;:::i;9952:67::-;10261:12;;9942:77;;-1:-1:-1;;;;;;10261:12:10;:26;10257:89;;10307:12;;;10289:57;;-1:-1:-1;;;10289:57:10;;-1:-1:-1;;;;;10307:12:10;;;;10289:39;;:57;;10329:7;;10338;;10289:57;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;10257:89;9195:1158;;9019:1334;;;;;:::o;2038:391:3:-;-1:-1:-1;;;;;;;;;;;;;;;;;2259:8:3;-1:-1:-1;;;;;2259:14:3;;2291:86;;;;;;;;2307:7;2291:86;;;;;;2316:25;2333:7;2316:16;:25::i;:::-;2291:86;;;;2343:8;2291:86;;;;2353:8;2291:86;;;;2363:13;2291:86;;;;;2403:4;2259:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2240:182;2038:391;-1:-1:-1;;;;;2038:391:3:o;2041:169:28:-;2096:16;2115:6;;-1:-1:-1;;;;;2131:17:28;;;-1:-1:-1;;;;;;2131:17:28;;;;;;2163:40;;2115:6;;;;;;;2163:40;;2096:16;2163:40;2086:124;2041:169;:::o;3794:218:8:-;3880:18;3915:13;3926:1;3880:18;3915:8;;:13;:::i;:::-;3908:21;;;:::i;:::-;3901:29;;;-1:-1:-1;463:1:8;3944:28;;3940:65;;3996:8;;3981:24;;-1:-1:-1;;;3981:24:8;;;;;;;;;:::i;3940:65::-;3870:142;3794:218;;:::o;2636:549:9:-;2774:20;2796:24;2867:44;2878:9;2889:12;2903:7;2867:10;:44::i;:::-;2832:79;;-1:-1:-1;2832:79:9;-1:-1:-1;3147:31:9;3153:10;2832:79;3147:5;:31::i;3188:766:3:-;3389:31;;:::i;:::-;3554:20;3577:26;3588:4;:14;;;3577:10;:26::i;:::-;3617:15;;;;3554:49;;-1:-1:-1;3617:19:3;3613:53;;3638:28;3650:4;:15;;;3638:11;:28::i;:::-;3755:8;-1:-1:-1;;;;;3755:13:3;;3777:12;3809:92;;;;;;;;3825:7;3809:92;;;;;;3834:25;3851:7;3834:16;:25::i;:::-;3809:92;;;;3861:8;3809:92;;;;3871:8;3809:92;;;;3899:1;3881:4;:15;;;:19;3809:92;;;;;3919:14;3755:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3677:270;3188:766;-1:-1:-1;;;;;;;3188:766:3:o;14604:172:10:-;14675:16;14748:21;14711:33;14748:21;14711:9;:33;:::i;:::-;14710:59;;;;:::i;1573:123:13:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:13:o;15000:139:10:-;15064:16;15099:33;15111:21;-1:-1:-1;;;;;15099:33:10;;;:::i;3520:362:9:-;3654:24;3732:21;3738:3;3743:9;3732:5;:21::i;:::-;-1:-1:-1;3866:9:9;;3520:362;-1:-1:-1;;3520:362:9:o;2186:130:13:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:13;;2186:130;-1:-1:-1;;;;;;2186:130:13:o;640:284:12:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;15363:147:10:-;15428:15;15469:33;15481:21;15469:9;:33;:::i;598:506:13:-;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;33943:19:37;;;34018:3;33996:16;-1:-1:-1;;;;;;33992:51:37;33987:2;33978:12;;33971:73;34069:2;34060:12;;33788:290;1057:40:13;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;8963:576:29:-;-1:-1:-1;;;;;9046:21:29;;9038:67;;;;-1:-1:-1;;;9038:67:29;;34822:2:37;9038:67:29;;;34804:21:37;34861:2;34841:18;;;34834:30;34900:34;34880:18;;;34873:62;-1:-1:-1;;;34951:18:37;;;34944:31;34992:19;;9038:67:29;34620:397:37;9038:67:29;-1:-1:-1;;;;;9201:18:29;;9176:22;9201:18;;;:9;:18;;;;;;9237:24;;;;9229:71;;;;-1:-1:-1;;;9229:71:29;;35224:2:37;9229:71:29;;;35206:21:37;35263:2;35243:18;;;35236:30;35302:34;35282:18;;;35275:62;-1:-1:-1;;;35353:18:37;;;35346:32;35395:19;;9229:71:29;35022:398:37;9229:71:29;-1:-1:-1;;;;;9334:18:29;;;;;;:9;:18;;;;;9355:23;;;9334:44;;9398:12;:22;;9372:6;;9334:18;9398:22;;9372:6;;9398:22;:::i;:::-;;;;-1:-1:-1;;9436:37:29;;6157:25:37;;;9462:1:29;;-1:-1:-1;;;;;9436:37:29;;;;;6145:2:37;6130:18;9436:37:29;;;;;;;3870:142:8;3794:218;;:::o;4650:191:3:-;4716:17;4762:10;4749:9;:23;4745:62;;4781:26;;-1:-1:-1;;;4781:26:3;;4797:9;4781:26;;;6157:25:37;6130:18;;4781:26:3;6011:177:37;4745:62:3;-1:-1:-1;4824:10:3;4650:191::o;5218:410::-;5371:15;5389:8;-1:-1:-1;;;;;5389:16:3;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5371:36;-1:-1:-1;;;;;;5421:21:3;;5417:54;;5451:20;;-1:-1:-1;;;5451:20:3;;;;;;;;;;;5417:54;5545:76;-1:-1:-1;;;;;5545:32:3;;5578:10;5598:8;5609:11;5545:32;:76::i;:::-;5277:351;5218:410;:::o;8254:389:29:-;-1:-1:-1;;;;;8337:21:29;;8329:65;;;;-1:-1:-1;;;8329:65:29;;36016:2:37;8329:65:29;;;35998:21:37;36055:2;36035:18;;;36028:30;36094:33;36074:18;;;36067:61;36145:18;;8329:65:29;35814:355:37;8329:65:29;8481:6;8465:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8497:18:29;;;;;;:9;:18;;;;;:28;;8519:6;;8497:18;:28;;8519:6;;8497:28;:::i;:::-;;;;-1:-1:-1;;8540:37:29;;6157:25:37;;;-1:-1:-1;;;;;8540:37:29;;;8557:1;;8540:37;;6145:2:37;6130:18;8540:37:29;;;;;;;5277:351:3;5218:410;:::o;845:241:32:-;1010:68;;;-1:-1:-1;;;;;36432:15:37;;;1010:68:32;;;36414:34:37;36484:15;;;36464:18;;;36457:43;36516:18;;;;36509:34;;;1010:68:32;;;;;;;;;;36349:18:37;;;;1010:68:32;;;;;;;;-1:-1:-1;;;;;1010:68:32;-1:-1:-1;;;1010:68:32;;;3585:69;;;;;;;;;;;;;;;;983:96;;1003:5;;1010:68;-1:-1:-1;;3585:69:32;;:27;;;1010:68;;3585:27;:69::i;:::-;3668:17;;3559:95;;-1:-1:-1;3668:21:32;3664:176;;3763:10;3752:30;;;;;;;;;;;;:::i;:::-;3744:85;;;;-1:-1:-1;;;3744:85:32;;36756:2:37;3744:85:32;;;36738:21:37;36795:2;36775:18;;;36768:30;36834:34;36814:18;;;36807:62;-1:-1:-1;;;36885:18:37;;;36878:40;36935:19;;3744:85:32;36554:406:37;3461:223:33;3594:12;3625:52;3647:6;3655:4;3661:1;3664:12;3594;1034:20;;4828:60;;;;-1:-1:-1;;;4828:60:33;;37574:2:37;4828:60:33;;;37556:21:37;37613:2;37593:18;;;37586:30;37652:31;37632:18;;;37625:59;37701:18;;4828:60:33;37372:353:37;4828:60:33;4900:12;4914:23;4941:6;-1:-1:-1;;;;;4941:11:33;4960:5;4967:4;4941:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4899:73;;;;4989:51;5006:7;5015:10;5027:12;7307;7335:7;7331:516;;;-1:-1:-1;7365:10:33;7358:17;;7331:516;7476:17;;:21;7472:365;;7670:10;7664:17;7730:15;7717:10;7713:2;7709:19;7702:44;7472:365;7809:12;7802:20;;-1:-1:-1;;;7802:20:33;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:37:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:37;238:16;;231:27;14:250::o;269:271::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;522:2;501:15;-1:-1:-1;;497:29:37;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:37:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:131::-;-1:-1:-1;;;;;845:31:37;;835:42;;825:70;;891:1;888;881:12;906:315;974:6;982;1035:2;1023:9;1014:7;1010:23;1006:32;1003:52;;;1051:1;1048;1041:12;1003:52;1090:9;1077:23;1109:31;1134:5;1109:31;:::i;:::-;1159:5;1211:2;1196:18;;;;1183:32;;-1:-1:-1;;;906:315:37:o;1418:158::-;1480:5;1525:3;1516:6;1511:3;1507:16;1503:26;1500:46;;;1542:1;1539;1532:12;1500:46;-1:-1:-1;1564:6:37;1418:158;-1:-1:-1;1418:158:37:o;1581:360::-;1669:6;1722:2;1710:9;1701:7;1697:23;1693:32;1690:52;;;1738:1;1735;1728:12;1690:52;1778:9;1765:23;-1:-1:-1;;;;;1803:6:37;1800:30;1797:50;;;1843:1;1840;1833:12;1797:50;1866:69;1927:7;1918:6;1907:9;1903:22;1866:69;:::i;2100:1336::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;2466:4;2514:3;2499:19;;2591:2;2629:3;2624:2;2613:9;2609:18;2602:31;2653:6;2688;2682:13;2719:6;2711;2704:22;2757:3;2746:9;2742:19;2735:26;;2820:3;2810:6;2807:1;2803:14;2792:9;2788:30;2784:40;2770:54;;2843:4;2882;2874:6;2870:17;2905:1;2915:429;2929:6;2926:1;2923:13;2915:429;;;2994:22;;;-1:-1:-1;;2990:37:37;2978:50;;3051:13;;3092:9;;3077:25;;3141:11;;3135:18;3173:15;;;3166:27;;;3216:48;3248:15;;;3135:18;3216:48;:::i;:::-;3206:58;-1:-1:-1;;3322:12:37;;;;3287:15;;;;2951:1;2944:9;2915:429;;;-1:-1:-1;;2020:12:37;;3426:2;3411:18;;2008:25;-1:-1:-1;;;2082:4:37;2071:16;;2065:23;2049:14;;;2042:47;-1:-1:-1;3361:6:37;-1:-1:-1;3376:54:37;1946:149;3649:154;3708:5;3753:2;3744:6;3739:3;3735:16;3731:25;3728:45;;;3769:1;3766;3759:12;3808:347;3859:8;3869:6;3923:3;3916:4;3908:6;3904:17;3900:27;3890:55;;3941:1;3938;3931:12;3890:55;-1:-1:-1;3964:20:37;;-1:-1:-1;;;;;3996:30:37;;3993:50;;;4039:1;4036;4029:12;3993:50;4076:4;4068:6;4064:17;4052:29;;4128:3;4121:4;4112:6;4104;4100:19;4096:30;4093:39;4090:59;;;4145:1;4142;4135:12;4090:59;3808:347;;;;;:::o;4160:1048::-;4303:6;4311;4319;4327;4335;4343;4351;4404:3;4392:9;4383:7;4379:23;4375:33;4372:53;;;4421:1;4418;4411:12;4372:53;4444;4489:7;4478:9;4444:53;:::i;:::-;4434:63;;4544:2;4533:9;4529:18;4516:32;4506:42;;4599:3;4588:9;4584:19;4571:33;-1:-1:-1;;;;;4664:2:37;4656:6;4653:14;4650:34;;;4680:1;4677;4670:12;4650:34;4719:58;4769:7;4760:6;4749:9;4745:22;4719:58;:::i;:::-;4796:8;;-1:-1:-1;4693:84:37;-1:-1:-1;4881:3:37;4866:19;;4853:33;;-1:-1:-1;4895:31:37;4853:33;4895:31;:::i;:::-;4945:5;;-1:-1:-1;5003:3:37;4988:19;;4975:33;;5020:16;;;5017:36;;;5049:1;5046;5039:12;5017:36;;5088:60;5140:7;5129:8;5118:9;5114:24;5088:60;:::i;:::-;4160:1048;;;;-1:-1:-1;4160:1048:37;;-1:-1:-1;4160:1048:37;;;;5062:86;;-1:-1:-1;;;4160:1048:37:o;6193:456::-;6270:6;6278;6286;6339:2;6327:9;6318:7;6314:23;6310:32;6307:52;;;6355:1;6352;6345:12;6307:52;6394:9;6381:23;6413:31;6438:5;6413:31;:::i;:::-;6463:5;-1:-1:-1;6520:2:37;6505:18;;6492:32;6533:33;6492:32;6533:33;:::i;:::-;6193:456;;6585:7;;-1:-1:-1;;;6639:2:37;6624:18;;;;6611:32;;6193:456::o;6843:163::-;6910:20;;6970:10;6959:22;;6949:33;;6939:61;;6996:1;6993;6986:12;6939:61;6843:163;;;:::o;7011:252::-;7078:6;7086;7139:2;7127:9;7118:7;7114:23;7110:32;7107:52;;;7155:1;7152;7145:12;7107:52;7178:28;7196:9;7178:28;:::i;7268:118::-;7354:5;7347:13;7340:21;7333:5;7330:32;7320:60;;7376:1;7373;7366:12;7391:489;7485:6;7493;7546:2;7534:9;7525:7;7521:23;7517:32;7514:52;;;7562:1;7559;7552:12;7514:52;7602:9;7589:23;-1:-1:-1;;;;;7627:6:37;7624:30;7621:50;;;7667:1;7664;7657:12;7621:50;7690:69;7751:7;7742:6;7731:9;7727:22;7690:69;:::i;:::-;7680:79;;;7809:2;7798:9;7794:18;7781:32;7822:28;7844:5;7822:28;:::i;:::-;7869:5;7859:15;;;7391:489;;;;;:::o;7885:257::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;8079:2;8064:18;;8091:45;1946:149;8147:159;8214:20;;8274:6;8263:18;;8253:29;;8243:57;;8296:1;8293;8286:12;8311:256;8377:6;8385;8438:2;8426:9;8417:7;8413:23;8409:32;8406:52;;;8454:1;8451;8444:12;8406:52;8477:28;8495:9;8477:28;:::i;:::-;8467:38;;8524:37;8557:2;8546:9;8542:18;8524:37;:::i;:::-;8514:47;;8311:256;;;;;:::o;9032:247::-;9091:6;9144:2;9132:9;9123:7;9119:23;9115:32;9112:52;;;9160:1;9157;9150:12;9112:52;9199:9;9186:23;9218:31;9243:5;9218:31;:::i;9489:395::-;9580:8;9590:6;9644:3;9637:4;9629:6;9625:17;9621:27;9611:55;;9662:1;9659;9652:12;9611:55;-1:-1:-1;9685:20:37;;-1:-1:-1;;;;;9717:30:37;;9714:50;;;9760:1;9757;9750:12;9714:50;9797:4;9789:6;9785:17;9773:29;;9857:3;9850:4;9840:6;9837:1;9833:14;9825:6;9821:27;9817:38;9814:47;9811:67;;;9874:1;9871;9864:12;9889:503;10013:6;10021;10074:2;10062:9;10053:7;10049:23;10045:32;10042:52;;;10090:1;10087;10080:12;10042:52;10130:9;10117:23;-1:-1:-1;;;;;10155:6:37;10152:30;10149:50;;;10195:1;10192;10185:12;10149:50;10234:98;10324:7;10315:6;10304:9;10300:22;10234:98;:::i;:::-;10351:8;;10208:124;;-1:-1:-1;9889:503:37;-1:-1:-1;;;;9889:503:37:o;10397:184::-;10455:6;10508:2;10496:9;10487:7;10483:23;10479:32;10476:52;;;10524:1;10521;10514:12;10476:52;10547:28;10565:9;10547:28;:::i;10768:553::-;10854:6;10862;10870;10878;10931:2;10919:9;10910:7;10906:23;10902:32;10899:52;;;10947:1;10944;10937:12;10899:52;10970:28;10988:9;10970:28;:::i;:::-;10960:38;;11017:37;11050:2;11039:9;11035:18;11017:37;:::i;:::-;11007:47;;11105:2;11094:9;11090:18;11077:32;-1:-1:-1;;;;;11124:6:37;11121:30;11118:50;;;11164:1;11161;11154:12;11118:50;11203:58;11253:7;11244:6;11233:9;11229:22;11203:58;:::i;:::-;10768:553;;;;-1:-1:-1;11280:8:37;-1:-1:-1;;;;10768:553:37:o;11829:657::-;11967:6;11975;11983;12027:9;12018:7;12014:23;12057:3;12053:2;12049:12;12046:32;;;12074:1;12071;12064:12;12046:32;12114:9;12101:23;-1:-1:-1;;;;;12139:6:37;12136:30;12133:50;;;12179:1;12176;12169:12;12133:50;12202:69;12263:7;12254:6;12243:9;12239:22;12202:69;:::i;:::-;12192:79;-1:-1:-1;;12305:2:37;-1:-1:-1;;12287:16:37;;12283:25;12280:45;;;12321:1;12318;12311:12;12280:45;;12359:2;12348:9;12344:18;12334:28;;12412:2;12401:9;12397:18;12384:32;12425:31;12450:5;12425:31;:::i;:::-;12475:5;12465:15;;;11829:657;;;;;:::o;12491:613::-;12735:4;12777:3;12766:9;12762:19;12754:27;;12814:6;12808:13;12797:9;12790:32;-1:-1:-1;;;;;12882:4:37;12874:6;12870:17;12864:24;12860:49;12853:4;12842:9;12838:20;12831:79;12957:4;12949:6;12945:17;12939:24;12972:62;13028:4;13017:9;13013:20;12999:12;2020;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;2042:47;1946:149;12972:62;-1:-1:-1;2020:12:37;;13093:3;13078:19;;2008:25;2082:4;2071:16;;2065:23;2049:14;;;2042:47;13043:55;1946:149;13109:388;13177:6;13185;13238:2;13226:9;13217:7;13213:23;13209:32;13206:52;;;13254:1;13251;13244:12;13206:52;13293:9;13280:23;13312:31;13337:5;13312:31;:::i;:::-;13362:5;-1:-1:-1;13419:2:37;13404:18;;13391:32;13432:33;13391:32;13432:33;:::i;13502:236::-;13587:6;13640:2;13628:9;13619:7;13615:23;13611:32;13608:52;;;13656:1;13653;13646:12;13608:52;13679:53;13724:7;13713:9;13679:53;:::i;13743:380::-;13822:1;13818:12;;;;13865;;;13886:61;;13940:4;13932:6;13928:17;13918:27;;13886:61;13993:2;13985:6;13982:14;13962:18;13959:38;13956:161;;14039:10;14034:3;14030:20;14027:1;14020:31;14074:4;14071:1;14064:15;14102:4;14099:1;14092:15;14128:127;14189:10;14184:3;14180:20;14177:1;14170:31;14220:4;14217:1;14210:15;14244:4;14241:1;14234:15;14937:356;15139:2;15121:21;;;15158:18;;;15151:30;15217:34;15212:2;15197:18;;15190:62;15284:2;15269:18;;14937:356::o;15298:127::-;15359:10;15354:3;15350:20;15347:1;15340:31;15390:4;15387:1;15380:15;15414:4;15411:1;15404:15;15430:125;15495:9;;;15516:10;;;15513:36;;;15529:18;;:::i;15966:127::-;16027:10;16022:3;16018:20;16015:1;16008:31;16058:4;16055:1;16048:15;16082:4;16079:1;16072:15;16098:335;16202:4;16260:11;16247:25;16354:2;16350:7;16339:8;16323:14;16319:29;16315:43;16295:18;16291:68;16281:96;;16373:1;16370;16363:12;16281:96;16394:33;;;;;16098:335;-1:-1:-1;;16098:335:37:o;16438:521::-;16515:4;16521:6;16581:11;16568:25;16675:2;16671:7;16660:8;16644:14;16640:29;16636:43;16616:18;16612:68;16602:96;;16694:1;16691;16684:12;16602:96;16721:33;;16773:20;;;-1:-1:-1;;;;;;16805:30:37;;16802:50;;;16848:1;16845;16838:12;16802:50;16881:4;16869:17;;-1:-1:-1;16912:14:37;16908:27;;;16898:38;;16895:58;;;16949:1;16946;16939:12;16964:184;17022:6;17075:2;17063:9;17054:7;17050:23;17046:32;17043:52;;;17091:1;17088;17081:12;17043:52;17114:28;17132:9;17114:28;:::i;17278:517::-;17379:2;17374:3;17371:11;17368:421;;;17415:5;17412:1;17405:16;17459:4;17456:1;17446:18;17529:2;17517:10;17513:19;17510:1;17506:27;17500:4;17496:38;17565:4;17553:10;17550:20;17547:47;;;-1:-1:-1;17588:4:37;17547:47;17643:2;17638:3;17634:12;17631:1;17627:20;17621:4;17617:31;17607:41;;17698:81;17716:2;17709:5;17706:13;17698:81;;;17775:1;17761:16;;17742:1;17731:13;17698:81;;17971:1194;-1:-1:-1;;;;;18088:3:37;18085:27;18082:53;;;18115:18;;:::i;:::-;18144:93;18233:3;18193:38;18225:4;18219:11;18193:38;:::i;:::-;18187:4;18144:93;:::i;:::-;18263:1;18288:2;18283:3;18280:11;18305:1;18300:607;;;;18951:1;18968:3;18965:93;;;-1:-1:-1;19024:19:37;;;19011:33;18965:93;-1:-1:-1;;17928:1:37;17924:11;;;17920:24;17916:29;17906:40;17952:1;17948:11;;;17903:57;19071:78;;18273:886;;18300:607;17225:1;17218:14;;;17262:4;17249:18;;-1:-1:-1;;18336:17:37;;;18450:229;18464:7;18461:1;18458:14;18450:229;;;18553:19;;;18540:33;18525:49;;18660:4;18645:20;;;;18613:1;18601:14;;;;18480:12;18450:229;;;18454:3;18707;18698:7;18695:16;18692:159;;;18831:1;18827:6;18821:3;18815;18812:1;18808:11;18804:21;18800:34;18796:39;18783:9;18778:3;18774:19;18761:33;18757:79;18749:6;18742:95;18692:159;;;18894:1;18888:3;18885:1;18881:11;18877:19;18871:4;18864:33;18273:886;;17971:1194;;;:::o;19170:266::-;19258:6;19253:3;19246:19;19310:6;19303:5;19296:4;19291:3;19287:14;19274:43;-1:-1:-1;19362:1:37;19337:16;;;19355:4;19333:27;;;19326:38;;;;19418:2;19397:15;;;-1:-1:-1;;19393:29:37;19384:39;;;19380:50;;19170:266::o;19441:1772::-;19696:2;19748:21;;;19721:18;;;19804:22;;;19667:4;;19845:2;19863:18;;;19927:1;19923:14;;;19908:30;;19904:39;;19966:6;19667:4;20000:1184;20014:6;20011:1;20008:13;20000:1184;;;20079:22;;;-1:-1:-1;;20075:36:37;20063:49;;20151:20;;20226:14;20222:27;;;-1:-1:-1;;20218:41:37;20194:66;;20184:94;;20274:1;20271;20264:12;20184:94;20304:31;;20358:4;20420:10;20394:24;20304:31;20394:24;:::i;:::-;20390:41;20382:6;20375:57;20508:6;20473:33;20502:2;20495:5;20491:14;20473:33;:::i;:::-;20469:46;20464:2;20456:6;20452:15;20445:71;20581:2;20574:5;20570:14;20557:28;20670:2;20666:7;20658:5;20642:14;20638:26;20634:40;20612:20;20608:67;20598:95;;20689:1;20686;20679:12;20598:95;20721:32;;;20829:16;;;;-1:-1:-1;20780:21:37;-1:-1:-1;;;;;20861:30:37;;20858:50;;;20904:1;20901;20894:12;20858:50;20957:6;20941:14;20937:27;20928:7;20924:41;20921:61;;;20978:1;20975;20968:12;20921:61;21019:2;21014;21006:6;21002:15;20995:27;21045:59;21100:2;21092:6;21088:15;21080:6;21071:7;21045:59;:::i;:::-;21162:12;;;;21035:69;-1:-1:-1;;;21127:15:37;;;;-1:-1:-1;20036:1:37;20029:9;20000:1184;;;-1:-1:-1;21201:6:37;;19441:1772;-1:-1:-1;;;;;;;;19441:1772:37:o;21218:331::-;21323:9;21334;21376:8;21364:10;21361:24;21358:44;;;21398:1;21395;21388:12;21358:44;21427:6;21417:8;21414:20;21411:40;;;21447:1;21444;21437:12;21411:40;-1:-1:-1;;21473:23:37;;;21518:25;;;;;-1:-1:-1;21218:331:37:o;21554:476::-;21745:3;21783:6;21777:13;21799:66;21858:6;21853:3;21846:4;21838:6;21834:17;21799:66;:::i;:::-;21887:16;;21940:6;21932;21887:16;21912:35;22004:1;21966:18;;21993:13;;;-1:-1:-1;21966:18:37;;21554:476;-1:-1:-1;;;21554:476:37:o;22035:244::-;22192:2;22181:9;22174:21;22155:4;22212:61;22269:2;22258:9;22254:18;22246:6;22238;22212:61;:::i;22284:331::-;22383:4;22441:11;22428:25;22535:3;22531:8;22520;22504:14;22500:29;22496:44;22476:18;22472:69;22462:97;;22555:1;22552;22545:12;22620:129;-1:-1:-1;;;;;22698:5:37;22694:30;22687:5;22684:41;22674:69;;22739:1;22736;22729:12;22754:992;23132:10;23105:25;23123:6;23105:25;:::i;:::-;23101:42;23090:9;23083:61;23207:4;23199:6;23195:17;23182:31;23175:4;23164:9;23160:20;23153:61;23064:4;23261;23253:6;23249:17;23236:31;23276:30;23300:5;23276:30;:::i;:::-;-1:-1:-1;;;;;23348:5:37;23344:30;23337:4;23326:9;23322:20;23315:60;;23411:6;23406:2;23395:9;23391:18;23384:34;23455:3;23449;23438:9;23434:19;23427:32;23482:62;23539:3;23528:9;23524:19;23516:6;23508;23482:62;:::i;:::-;-1:-1:-1;;;;;23581:32:37;;23601:3;23560:19;;23553:61;23651:22;;;23645:3;23630:19;;23623:51;23691:49;23655:6;23725;23717;23691:49;:::i;:::-;23683:57;22754:992;-1:-1:-1;;;;;;;;;;22754:992:37:o;23751:246::-;23818:2;23812:9;;;23848:15;;-1:-1:-1;;;;;23878:34:37;;23914:22;;;23875:62;23872:88;;;23940:18;;:::i;:::-;23976:2;23969:22;23751:246;:::o;24002:896::-;24081:6;24134:2;24122:9;24113:7;24109:23;24105:32;24102:52;;;24150:1;24147;24140:12;24102:52;24183:9;24177:16;-1:-1:-1;;;;;24253:2:37;24245:6;24242:14;24239:34;;;24269:1;24266;24259:12;24239:34;24307:6;24296:9;24292:22;24282:32;;24352:7;24345:4;24341:2;24337:13;24333:27;24323:55;;24374:1;24371;24364:12;24323:55;24403:2;24397:9;24425:2;24421;24418:10;24415:36;;;24431:18;;:::i;:::-;24506:2;24500:9;24474:2;24560:13;;-1:-1:-1;;24556:22:37;;;24580:2;24552:31;24548:40;24536:53;;;24604:18;;;24624:22;;;24601:46;24598:72;;;24650:18;;:::i;:::-;24690:10;24686:2;24679:22;24725:2;24717:6;24710:18;24765:7;24760:2;24755;24751;24747:11;24743:20;24740:33;24737:53;;;24786:1;24783;24776:12;24737:53;24799:68;24864:2;24859;24851:6;24847:15;24842:2;24838;24834:11;24799:68;:::i;24903:343::-;24992:6;25045:2;25033:9;25024:7;25020:23;25016:32;25013:52;;;25061:1;25058;25051:12;25013:52;25087:17;;:::i;:::-;25140:9;25127:23;25120:5;25113:38;25211:2;25200:9;25196:18;25183:32;25178:2;25171:5;25167:14;25160:56;25235:5;25225:15;;;24903:343;;;;:::o;27184:245::-;27242:6;27295:2;27283:9;27274:7;27270:23;27266:32;27263:52;;;27311:1;27308;27301:12;27263:52;27350:9;27337:23;27369:30;27393:5;27369:30;:::i;27434:479::-;27701:1;27697;27692:3;27688:11;27684:19;27676:6;27672:32;27661:9;27654:51;27741:6;27736:2;27725:9;27721:18;27714:34;27796:6;27788;27784:19;27779:2;27768:9;27764:18;27757:47;27840:3;27835:2;27824:9;27820:18;27813:31;27635:4;27861:46;27902:3;27891:9;27887:19;27879:6;27861:46;:::i;29135:379::-;29328:2;29317:9;29310:21;29291:4;29354:45;29395:2;29384:9;29380:18;29372:6;29354:45;:::i;:::-;29447:9;29439:6;29435:22;29430:2;29419:9;29415:18;29408:50;29475:33;29501:6;29493;29475:33;:::i;29519:245::-;29586:6;29639:2;29627:9;29618:7;29614:23;29610:32;29607:52;;;29655:1;29652;29645:12;29607:52;29687:9;29681:16;29706:28;29728:5;29706:28;:::i;29769:891::-;29992:2;29981:9;29974:21;30050:10;30041:6;30035:13;30031:30;30026:2;30015:9;30011:18;30004:58;30116:4;30108:6;30104:17;30098:24;30093:2;30082:9;30078:18;30071:52;29955:4;30170:2;30162:6;30158:15;30152:22;30211:4;30205:3;30194:9;30190:19;30183:33;30239:52;30286:3;30275:9;30271:19;30257:12;30239:52;:::i;:::-;30225:66;;30340:2;30332:6;30328:15;30322:22;30414:2;30410:7;30398:9;30390:6;30386:22;30382:36;30375:4;30364:9;30360:20;30353:66;30442:41;30476:6;30460:14;30442:41;:::i;:::-;30552:3;30540:16;;;;30534:23;30527:31;30520:39;30514:3;30499:19;;30492:68;-1:-1:-1;;;;;;;;30621:32:37;;;;30614:4;30599:20;;;30592:62;30428:55;29769:891::o;30665:279::-;30735:5;30783:4;30771:9;30766:3;30762:19;30758:30;30755:50;;;30801:1;30798;30791:12;30755:50;30823:17;;:::i;:::-;30814:26;;30869:9;30863:16;30856:5;30849:31;30933:2;30922:9;30918:18;30912:25;30907:2;30900:5;30896:14;30889:49;30665:279;;;;:::o;30949:259::-;31049:6;31102:2;31090:9;31081:7;31077:23;31073:32;31070:52;;;31118:1;31115;31108:12;31070:52;31141:61;31194:7;31183:9;31141:61;:::i;31213:318::-;-1:-1:-1;;;;;;31333:19:37;;31404:11;;;;31435:1;31427:10;;31424:101;;;31512:2;31506;31499:3;31496:1;31492:11;31489:1;31485:19;31481:28;31477:2;31473:37;31469:46;31460:55;;31424:101;;;31213:318;;;;:::o;31536:683::-;31640:6;31693:3;31681:9;31672:7;31668:23;31664:33;31661:53;;;31710:1;31707;31700:12;31661:53;31743:2;31737:9;31785:4;31777:6;31773:17;31856:6;31844:10;31841:22;-1:-1:-1;;;;;31808:10:37;31805:34;31802:62;31799:88;;;31867:18;;:::i;:::-;31903:2;31896:22;31942:16;;31927:32;;32002:2;31987:18;;31981:25;32015:30;31981:25;32015:30;:::i;:::-;32073:2;32061:15;;32054:30;32117:70;32179:7;32174:2;32159:18;;32117:70;:::i;:::-;32112:2;32100:15;;32093:95;32104:6;31536:683;-1:-1:-1;;;31536:683:37:o;32224:217::-;32264:1;32290;32280:132;;32334:10;32329:3;32325:20;32322:1;32315:31;32369:4;32366:1;32359:15;32397:4;32394:1;32387:15;32280:132;-1:-1:-1;32426:9:37;;32224:217::o;32446:168::-;32519:9;;;32550;;32567:15;;;32561:22;;32547:37;32537:71;;32588:18;;:::i;32619:255::-;32739:19;;32778:2;32770:11;;32767:101;;;-1:-1:-1;;32839:2:37;32835:12;;;32832:1;32828:20;32824:33;32813:45;32619:255;;;;:::o;32879:331::-;-1:-1:-1;;;;;;32999:19:37;;33083:11;;;;33114:1;33106:10;;33103:101;;;33175:1;33171:11;;;;33168:1;33164:19;33160:28;;;33152:37;33148:46;;;;32879:331;-1:-1:-1;;32879:331:37:o;33215:568::-;-1:-1:-1;;;;;33480:3:37;33476:28;33467:6;33462:3;33458:16;33454:51;33449:3;33442:64;33566:10;33561:3;33557:20;33548:6;33543:3;33539:16;33535:43;33531:1;33526:3;33522:11;33515:64;33609:6;33604:2;33599:3;33595:12;33588:28;33424:3;33645:6;33639:13;33661:75;33729:6;33724:2;33719:3;33715:12;33708:4;33700:6;33696:17;33661:75;:::i;:::-;33756:16;;;;33774:2;33752:25;;33215:568;-1:-1:-1;;;;;33215:568:37:o;34083:532::-;34324:6;34319:3;34312:19;-1:-1:-1;;;;;34387:3:37;34383:28;34374:6;34369:3;34365:16;34361:51;34356:2;34351:3;34347:12;34340:73;34443:6;34438:2;34433:3;34429:12;34422:28;34294:3;34479:6;34473:13;34495:73;34561:6;34556:2;34551:3;34547:12;34542:2;34534:6;34530:15;34495:73;:::i;:::-;34588:16;;;;34606:2;34584:25;;34083:532;-1:-1:-1;;;;;34083:532:37:o;35425:128::-;35492:9;;;35513:11;;;35510:37;;;35527:18;;:::i;35558:251::-;35628:6;35681:2;35669:9;35660:7;35656:23;35652:32;35649:52;;;35697:1;35694;35687:12;35649:52;35729:9;35723:16;35748:31;35773:5;35748:31;:::i;37730:287::-;37859:3;37897:6;37891:13;37913:66;37972:6;37967:3;37960:4;37952:6;37948:17;37913:66;:::i
Swarm Source
ipfs://adddb22f372ce8677d15a9daf6cdcc60363ee043eac004b0cd4669945089b984