Overview
S Balance
S Value
$0.00Latest 25 from a total of 60 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Send | 7919054 | 9 hrs ago | IN | 0.10019939 S | 0.01832696 | ||||
Send | 7859571 | 18 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7859138 | 18 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7859110 | 18 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7859084 | 18 hrs ago | IN | 0.18439115 S | 0.01891131 | ||||
Send | 7854196 | 19 hrs ago | IN | 0.18439115 S | 0.01906572 | ||||
Send | 7854062 | 19 hrs ago | IN | 0.18439115 S | 0.01733497 | ||||
Send | 7854029 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853925 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853923 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853876 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853836 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853830 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853750 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853645 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7853643 | 19 hrs ago | IN | 0.18439115 S | 0.02921625 | ||||
Send | 7853594 | 19 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7852185 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7852064 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7852059 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7852040 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7852024 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7851853 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 | ||||
Send | 7851825 | 20 hrs ago | IN | 0.18439115 S | 0.01733497 | ||||
Send | 7851806 | 20 hrs ago | IN | 0.18439115 S | 0.01733563 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
7919054 | 9 hrs ago | 0.10019939 S | ||||
7859571 | 18 hrs ago | 0.18439115 S | ||||
7859138 | 18 hrs ago | 0.18439115 S | ||||
7859110 | 18 hrs ago | 0.18439115 S | ||||
7859084 | 18 hrs ago | 0.18439115 S | ||||
7854196 | 19 hrs ago | 0.18439115 S | ||||
7854062 | 19 hrs ago | 0.18439115 S | ||||
7854029 | 19 hrs ago | 0.18439115 S | ||||
7853925 | 19 hrs ago | 0.18439115 S | ||||
7853923 | 19 hrs ago | 0.18439115 S | ||||
7853876 | 19 hrs ago | 0.18439115 S | ||||
7853836 | 19 hrs ago | 0.18439115 S | ||||
7853830 | 19 hrs ago | 0.18439115 S | ||||
7853750 | 19 hrs ago | 0.18439115 S | ||||
7853645 | 19 hrs ago | 0.18439115 S | ||||
7853643 | 19 hrs ago | 0.18439115 S | ||||
7853594 | 19 hrs ago | 0.18439115 S | ||||
7852185 | 20 hrs ago | 0.18439115 S | ||||
7852064 | 20 hrs ago | 0.18439115 S | ||||
7852059 | 20 hrs ago | 0.18439115 S | ||||
7852040 | 20 hrs ago | 0.18439115 S | ||||
7852024 | 20 hrs ago | 0.18439115 S | ||||
7851853 | 20 hrs ago | 0.18439115 S | ||||
7851825 | 20 hrs ago | 0.18439115 S | ||||
7851806 | 20 hrs ago | 0.18439115 S |
Loading...
Loading
Contract Name:
WBTCOFT
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTFee } from "./OFTFee.sol"; contract WBTCOFT is OFTFee { constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _owner ) OFTFee(_name, _symbol, _lzEndpoint, _owner) {} function decimals() public pure override returns (uint8) { return 8; } function sharedDecimals() public pure override returns (uint8) { return 8; } }
// 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 Indicates whether an address is an approved composeMsg sender to the Endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata _origin, bytes calldata _message, address _sender ) external view returns (bool isSender); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol"; /** * @title OAppOptionsType3 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options. */ abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable { uint16 internal constant OPTION_TYPE_3 = 3; // @dev The "msgType" should be defined in the child contract. mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions; /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner { _setEnforcedOptions(_enforcedOptions); } /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual { for (uint256 i = 0; i < _enforcedOptions.length; i++) { // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining. _assertOptionsType3(_enforcedOptions[i].options); enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options; } emit EnforcedOptionSet(_enforcedOptions); } /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OAPP message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. * * @dev If there is an enforced lzReceive option: * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether} * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function. * @dev This presence of duplicated options is handled off-chain in the verifier/executor. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) public view virtual returns (bytes memory) { bytes memory enforced = enforcedOptions[_eid][_msgType]; // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options. if (enforced.length == 0) return _extraOptions; // No caller options, return enforced if (_extraOptions.length == 0) return enforced; // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined. if (_extraOptions.length >= 2) { _assertOptionsType3(_extraOptions); // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced. return bytes.concat(enforced, _extraOptions[2:]); } // No valid set of options was found. revert InvalidOptions(_extraOptions); } /** * @dev Internal function to assert that options are of type 3. * @param _options The options to be checked. */ function _assertOptionsType3(bytes memory _options) internal pure virtual { uint16 optionsType; assembly { optionsType := mload(add(_options, 2)) } if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @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 { _setPeer(_eid, _peer); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function _setPeer(uint32 _eid, bytes32 _peer) internal virtual { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { bytes32 peer = peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) public onlyOwner { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppReceiver * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers. */ abstract contract OAppReceiver is IOAppReceiver, OAppCore { // Custom error message for when the caller is not the registered endpoint/ error OnlyEndpoint(address addr); // @dev The version of the OAppReceiver implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant RECEIVER_VERSION = 2; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. * ie. this is a RECEIVE only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions. */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (0, RECEIVER_VERSION); } /** * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint. * @dev _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @dev _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata /*_origin*/, bytes calldata /*_message*/, address _sender ) public view virtual returns (bool) { return _sender == address(this); } /** * @notice Checks if the path initialization is allowed based on the provided origin. * @param origin The origin information containing the source endpoint and sender address. * @return Whether the path has been initialized. * * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received. * @dev This defaults to assuming if a peer has been set, its initialized. * Can be overridden by the OApp if there is other logic to determine this. */ function allowInitializePath(Origin calldata origin) public view virtual returns (bool) { return peers[origin.srcEid] == origin.sender; } /** * @notice Retrieves the next nonce for a given source endpoint and sender address. * @dev _srcEid The source endpoint ID. * @dev _sender The sender address. * @return nonce The next nonce. * * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement. * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered. * @dev This is also enforced by the OApp. * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0. */ function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) { return 0; } /** * @dev Entry point for receiving messages or packets from the endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The payload of the received message. * @param _executor The address of the executor for the received message. * @param _extraData Additional arbitrary data provided by the corresponding executor. * * @dev Entry point for receiving msg/packet from the LayerZero endpoint. */ function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) public payable virtual { // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp. if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender); // Ensure that the sender matches the expected peer for the source endpoint. if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender); // Call the internal OApp implementation of lzReceive. _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppSender is OAppCore { using SafeERC20 for IERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote( uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken ) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return // solhint-disable-next-line check-send-result endpoint.send{ value: messageValue }( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value != _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT 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.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.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 _gracePeriod) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface 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.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { FeeConfig, IFee } from "./interfaces/IFee.sol"; /** * @title Fee * @notice Implements fee configuration and calculation. */ abstract contract Fee is IFee, Ownable { uint16 public constant BPS_DENOMINATOR = 10_000; /** * @dev Default fee basis points (BPS) for all destinations. */ uint16 public defaultFeeBps; /** * @dev Fee configuration for a specific destination LayerZero endpoint ID. */ mapping(uint32 dstEid => FeeConfig config) public feeBps; /** * @dev Sets the default fee basis points (BPS) for all destinations. */ function setDefaultFeeBps(uint16 _feeBps) external onlyOwner { if (_feeBps >= BPS_DENOMINATOR) revert IFee.InvalidBps(); defaultFeeBps = _feeBps; emit DefaultFeeBpsSet(_feeBps); } /** * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID. */ function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external onlyOwner { if (_feeBps >= BPS_DENOMINATOR) revert IFee.InvalidBps(); feeBps[_dstEid] = FeeConfig(_feeBps, _enabled); emit FeeBpsSet(_dstEid, _feeBps, _enabled); } /** * @dev Returns the fee for a specific destination LayerZero EndpointV2 ID. */ function getFee(uint32 _dstEid, uint256 _amount) public view virtual returns (uint256) { uint16 bps = _getFeeBps(_dstEid); return bps == 0 ? 0 : (_amount * bps) / BPS_DENOMINATOR; } function _getFeeBps(uint32 _dstEid) internal view returns (uint16) { FeeConfig memory config = feeBps[_dstEid]; if (config.enabled) { return config.feeBps; } else if (defaultFeeBps > 0) { return defaultFeeBps; } return 0; } }
// SPDX-LICENSE-IDENTIFIER: MIT pragma solidity ^0.8.0; struct FeeConfig { uint16 feeBps; bool enabled; } /** * @title Fee interface. * @notice A generic interface for collecting fees. */ interface IFee { // errors error InvalidBps(); error InvalidFeeOwner(); // events event FeeBpsSet(uint32 dstEid, uint16 feeBps, bool enabled); event DefaultFeeBpsSet(uint16 feeBps); // setters /** * @dev Sets the default fee basis points (BPS) for all destinations. */ function setDefaultFeeBps(uint16 _feeBps) external; /** * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID. */ function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { MessagingReceipt, MessagingFee } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppSender.sol"; /** * @dev Struct representing token parameters for the OFT send() operation. */ struct SendParam { uint32 dstEid; // Destination endpoint ID. bytes32 to; // Recipient address. uint256 amountLD; // Amount to send in local decimals. uint256 minAmountLD; // Minimum amount to send in local decimals. bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message. bytes composeMsg; // The composed message for the send() operation. bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. } /** * @dev Struct representing OFT limit information. * @dev These amounts can change dynamically and are up the the specific oft implementation. */ struct OFTLimit { uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient. uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient. } /** * @dev Struct representing OFT receipt information. */ struct OFTReceipt { uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals. // @dev In non-default implementations, the amountReceivedLD COULD differ from this value. uint256 amountReceivedLD; // Amount of tokens to be received on the remote side. } /** * @dev Struct representing OFT fee details. * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI. */ struct OFTFeeDetail { int256 feeAmountLD; // Amount of the fee in local decimals. string description; // Description of the fee. } /** * @title IOFT * @dev Interface for the OftChain (OFT) token. * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well. * @dev This specific interface ID is '0x02e49c2c'. */ interface IOFT { // Custom error messages error InvalidLocalDecimals(); error SlippageExceeded(uint256 amountLD, uint256 minAmountLD); // Events event OFTSent( bytes32 indexed guid, // GUID of the OFT message. uint32 dstEid, // Destination Endpoint ID. address indexed fromAddress, // Address of the sender on the src chain. uint256 amountSentLD, // Amount of tokens sent in local decimals. uint256 amountReceivedLD // Amount of tokens received in local decimals. ); event OFTReceived( bytes32 indexed guid, // GUID of the OFT message. uint32 srcEid, // Source Endpoint ID. address indexed toAddress, // Address of the recipient on the dst chain. uint256 amountReceivedLD // Amount of tokens received in local decimals. ); /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external view returns (bytes4 interfaceId, uint64 version); /** * @notice Retrieves the address of the token associated with the OFT. * @return token The address of the ERC20 token implementation. */ function token() external view returns (address); /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev Allows things like wallet implementers to determine integration requirements, * without understanding the underlying token implementation. */ function approvalRequired() external view returns (bool); /** * @notice Retrieves the shared decimals of the OFT. * @return sharedDecimals The shared decimals of the OFT. */ function sharedDecimals() external view returns (uint8); /** * @notice Provides a quote for OFT-related operations. * @param _sendParam The parameters for the send operation. * @return limit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return receipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory); /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return fee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory); /** * @notice Executes the send() operation. * @param _sendParam The parameters for the send operation. * @param _fee The fee information supplied by the caller. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds from fees etc. on the src. * @return receipt The LayerZero messaging receipt from the send() operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable returns (MessagingReceipt memory, OFTReceipt memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library 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 { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IOFT, OFTCore } from "./OFTCore.sol"; /** * @title OFT Contract * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract. */ abstract contract OFT is OFTCore, ERC20 { /** * @dev Constructor for the OFT contract. * @param _name The name of the OFT. * @param _symbol The symbol of the OFT. * @param _lzEndpoint The LayerZero endpoint address. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _delegate ) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {} /** * @dev Retrieves the address of the underlying ERC20 implementation. * @return The address of the OFT token. * * @dev In the case of OFT, address(this) and erc20 are the same contract. */ function token() public view returns (address) { return address(this); } /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev In the case of OFT where the contract IS the token, approval is NOT required. */ function approvalRequired() external pure virtual returns (bool) { return false; } /** * @dev Burns tokens from the sender's specified balance. * @param _from The address to debit the tokens from. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90, // therefore amountSentLD CAN differ from amountReceivedLD. // @dev Default OFT burns on src. _burn(_from, amountSentLD); } /** * @dev Credits tokens to the specified address. * @param _to The address to credit the tokens to. * @param _amountLD The amount of tokens to credit in local decimals. * @dev _srcEid The source chain ID. * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals. */ function _credit( address _to, uint256 _amountLD, uint32 /*_srcEid*/ ) internal virtual override returns (uint256 amountReceivedLD) { if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0) // @dev Default OFT mints on dst. _mint(_to, _amountLD); // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IOFT, OFTCore } from "./OFTCore.sol"; /** * @title OFTAdapter Contract * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality. * * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility. * @dev WARNING: ONLY 1 of these should exist for a given global mesh, * unless you make a NON-default implementation of OFT and needs to be done very carefully. * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD. */ abstract contract OFTAdapter is OFTCore { using SafeERC20 for IERC20; IERC20 internal immutable innerToken; /** * @dev Constructor for the OFTAdapter contract. * @param _token The address of the ERC-20 token to be adapted. * @param _lzEndpoint The LayerZero endpoint address. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor( address _token, address _lzEndpoint, address _delegate ) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) { innerToken = IERC20(_token); } /** * @dev Retrieves the address of the underlying ERC20 implementation. * @return The address of the adapted ERC-20 token. * * @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract. */ function token() public view returns (address) { return address(innerToken); } /** * @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 default OFTAdapter, approval is required. * @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval. */ function approvalRequired() external pure virtual returns (bool) { return true; } /** * @dev Locks tokens from the sender's specified balance in this contract. * @param _from The address to debit from. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. * * @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract. * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountReceivedLD. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); // @dev Lock tokens by moving them into this contract from the caller. innerToken.safeTransferFrom(_from, address(this), 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. * * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountReceivedLD. */ function _credit( address _to, uint256 _amountLD, uint32 /*_srcEid*/ ) internal virtual override returns (uint256 amountReceivedLD) { // @dev Unlock the tokens and transfer to the recipient. innerToken.safeTransfer(_to, _amountLD); // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OApp, Origin } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol"; import { OAppOptionsType3 } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OAppOptionsType3.sol"; import { IOAppMsgInspector } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/IOAppMsgInspector.sol"; import { OAppPreCrimeSimulator } from "@layerzerolabs/lz-evm-oapp-v2/contracts/precrime/OAppPreCrimeSimulator.sol"; import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol"; import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol"; import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol"; /** * @title OFTCore * @dev Abstract contract for the OftChain (OFT) token. */ abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 { using OFTMsgCodec for bytes; using OFTMsgCodec for bytes32; // @notice Provides a conversion rate when swapping between denominations of SD and LD // - shareDecimals == SD == shared Decimals // - localDecimals == LD == local decimals // @dev Considers that tokens have different decimal amounts on various chains. // @dev eg. // For a token // - locally with 4 decimals --> 1.2345 => uint(12345) // - remotely with 2 decimals --> 1.23 => uint(123) // - The conversion rate would be 10 ** (4 - 2) = 100 // @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote, // you can only display 1.23 -> uint(123). // @dev To preserve the dust that would otherwise be lost on that conversion, // we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh uint256 public immutable decimalConversionRate; // @notice Msg types that are used to identify the various OFT operations. // @dev This can be extended in child contracts for non-default oft operations // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol. uint16 public constant SEND = 1; uint16 public constant SEND_AND_CALL = 2; // Address of an optional contract to inspect both 'message' and 'options' address public msgInspector; event MsgInspectorSet(address inspector); /** * @dev Constructor. * @param _localDecimals The decimals of the token on the local chain (this chain). * @param _endpoint The address of the LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) { if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals(); decimalConversionRate = 10 ** (_localDecimals - sharedDecimals()); } /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) { return (type(IOFT).interfaceId, 1); } /** * @dev Retrieves the shared decimals of the OFT. * @return The shared decimals of the OFT. * * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap * Lowest common decimal denominator between chains. * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64). * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller. * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615 */ function sharedDecimals() public view virtual returns (uint8) { return 6; } /** * @dev Sets the message inspector address for the OFT. * @param _msgInspector The address of the message inspector. * * @dev This is an optional contract that can be used to inspect both 'message' and 'options'. * @dev Set it to address(0) to disable it, or set it to a contract address to enable it. */ function setMsgInspector(address _msgInspector) public virtual onlyOwner { msgInspector = _msgInspector; emit MsgInspectorSet(_msgInspector); } /** * @notice Provides a quote for OFT-related operations. * @param _sendParam The parameters for the send operation. * @return oftLimit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return oftReceipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view virtual returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt) { uint256 minAmountLD = 0; // Unused in the default implementation. uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation. oftLimit = OFTLimit(minAmountLD, maxAmountLD); // Unused in the default implementation; reserved for future complex fee details. oftFeeDetails = new OFTFeeDetail[](0); // @dev This is the same as the send() operation, but without the actual send. // - amountSentLD is the amount in local decimals that would be sent from the sender. // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance. // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does. (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView( _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); } /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return msgFee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend( SendParam calldata _sendParam, bool _payInLzToken ) external view virtual returns (MessagingFee memory msgFee) { // @dev mock the amount to receive, this is the same operation used in the send(). // The quote is as similar as possible to the actual send() operation. (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Calculates the LayerZero fee for the send() operation. return _quote(_sendParam.dstEid, message, options, _payInLzToken); } /** * @dev Executes the send operation. * @param _sendParam The parameters for the send operation. * @param _fee The calculated fee for the send() operation. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds. * @return msgReceipt The receipt for the send operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) { // @dev Applies the token transfers regarding this send() operation. // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender. // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance. (uint256 amountSentLD, uint256 amountReceivedLD) = _debit( msg.sender, _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt. msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress); // @dev Formulate the OFT receipt. oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD); } /** * @dev Internal function to build the message and options. * @param _sendParam The parameters for the send() operation. * @param _amountLD The amount in local decimals. * @return message The encoded message. * @return options The encoded options. */ function _buildMsgAndOptions( SendParam calldata _sendParam, uint256 _amountLD ) internal view virtual returns (bytes memory message, bytes memory options) { bool hasCompose; // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is. (message, hasCompose) = OFTMsgCodec.encode( _sendParam.to, _toSD(_amountLD), // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote. // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01' _sendParam.composeMsg ); // @dev Change the msg type depending if its composed or not. uint16 msgType = hasCompose ? SEND_AND_CALL : SEND; // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3. options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions); // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector. // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean 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 _from The address to debit. * @param _amountLD The amount to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination endpoint ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD); /** * @dev Internal function to perform a credit operation. * @param _to The address to credit. * @param _amountLD The amount to credit in local decimals. * @param _srcEid The source endpoint ID. * @return amountReceivedLD The amount ACTUALLY received in local decimals. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _credit( address _to, uint256 _amountLD, uint32 _srcEid ) internal virtual returns (uint256 amountReceivedLD); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OFTFeeAdapter } from "../OFTFeeAdapter.sol"; // @dev WARNING: This is for testing purposes only contract MyOFTFeeAdapterMock is OFTFeeAdapter { constructor(address _token, address _lzEndpoint, address _delegate) OFTFeeAdapter(_token, _lzEndpoint, _delegate) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OFTFee } from "../OFTFee.sol"; // @dev WARNING: This is for testing purposes only contract MyOFTFeeMock is OFTFee { constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _delegate ) OFTFee(_name, _symbol, _lzEndpoint, _delegate) {} function mint(address _to, uint256 _amount) public { _mint(_to, _amount); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // @dev WARNING: This is for testing purposes only contract WBTCMock is ERC20 { constructor() ERC20("WBTC Mock", "WBTC") {} function mint(address _to, uint256 _amount) public { _mint(_to, _amount); } function decimals() public pure override returns (uint8) { return 8; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol"; import { Fee } from "@layerzerolabs/oft-evm/contracts/Fee.sol"; /** * @title OFTFee Contract * @notice OFT with fees. */ abstract contract OFTFee is OFT, Fee { address public feeOwner; event FeeOwnerSet(address _feeOwner); constructor( string memory _name, string memory _symbol, address _lzEndpoint, address _owner ) OFT(_name, _symbol, _lzEndpoint, _owner) Ownable(_owner) { feeOwner = _owner; } function setFeeOwner(address _feeOwner) external onlyOwner { if (_feeOwner == address(0)) revert InvalidFeeOwner(); feeOwner = _feeOwner; emit FeeOwnerSet(_feeOwner); } function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; // @dev Apply the fee, then de-dust the amount afterwards. // This means the fee is taken from the amount before the dust is removed. uint256 fee = getFee(_dstEid, _amountLD); amountReceivedLD = _removeDust(_amountLD - fee); // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); uint256 fee = amountSentLD - amountReceivedLD; if (fee > 0) { _transfer(_from, feeOwner, fee); } _burn(_from, amountReceivedLD); } }
// SPDX-LICENSE-IDENTIFIER: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IERC20, SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { OFTAdapter } from "@layerzerolabs/oft-evm/contracts/OFTAdapter.sol"; import { Fee } from "@layerzerolabs/oft-evm/contracts/Fee.sol"; /** * @title OFTFeeAdapter * @notice OFTAdepter with fees. */ abstract contract OFTFeeAdapter is OFTAdapter, Fee { using SafeERC20 for IERC20; uint256 public feeBalance; error NoFeesToWithdraw(); event FeeWithdrawn(address indexed to, uint256 amountLD); constructor( address _token, address _lzEndpoint, address _owner ) OFTAdapter(_token, _lzEndpoint, _owner) Ownable(_owner) {} // @dev Fees accumulate inside of the contract to save gas, and then can be withdrawn by the owner. function withdrawFees(address _to) external onlyOwner { // @dev doesn't allow owner to pull from the locked assets of the contract, // only from accumulated fees uint256 balance = feeBalance; if (balance == 0) revert NoFeesToWithdraw(); feeBalance = 0; innerToken.safeTransfer(_to, balance); emit FeeWithdrawn(_to, balance); } function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; // @dev Apply the fee, then de-dust the amount afterwards. // This means the fee is taken from the amount before the dust is removed. uint256 fee = getFee(_dstEid, _amountLD); amountReceivedLD = _removeDust(_amountLD - fee); // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); innerToken.safeTransferFrom(_from, address(this), amountSentLD); if (amountSentLD > amountReceivedLD) { // @dev increment the total fees that can be withdrawn feeBalance += (amountSentLD - amountReceivedLD); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { IERC20, SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title Swap * @dev Exchange IERC20 tokens with the same number of decimals with a 1:1 exchange rate. */ contract Swap is Ownable { using SafeERC20 for IERC20; error DecimalsMismatch(); error NativeGasNotAccepted(); IERC20 public immutable fromToken; IERC20 public immutable toToken; event Swapped(address indexed user, uint256 amount); event Withdrawn(IERC20 token, uint256 amount); constructor(IERC20 _fromToken, IERC20 _toToken) Ownable(msg.sender) { if (IERC20Metadata(address(_fromToken)).decimals() != IERC20Metadata(address(_toToken)).decimals()) { revert DecimalsMismatch(); } fromToken = _fromToken; toToken = _toToken; } function swap(uint256 _amount) external { fromToken.safeTransferFrom(msg.sender, address(this), _amount); toToken.safeTransfer(msg.sender, _amount); emit Swapped(msg.sender, _amount); } function withdraw(IERC20 _token, uint256 _amount) external onlyOwner { _token.safeTransfer(msg.sender, _amount); emit Withdrawn(_token, _amount); } fallback() external { revert NativeGasNotAccepted(); } receive() external payable { revert NativeGasNotAccepted(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTFeeAdapter } from "./OFTFeeAdapter.sol"; contract WBTCOFTAdapter is OFTFeeAdapter { constructor(address _token, address _lzEndpoint, address _owner) OFTFeeAdapter(_token, _lzEndpoint, _owner) {} function sharedDecimals() public pure override returns (uint8) { return 8; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
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":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidBps","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidFeeOwner","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"DefaultFeeBpsSet","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":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"FeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_feeOwner","type":"address"}],"name":"FeeOwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"defaultFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"}],"name":"feeBps","outputs":[{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"bool","name":"enabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBps","type":"uint16"}],"name":"setDefaultFeeBps","outputs":[],"stateMutability":"nonpayable","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":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint16","name":"_feeBps","type":"uint16"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeOwner","type":"address"}],"name":"setFeeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162003bf138038062003bf18339810160408190526200003491620002fb565b8383838383838383838360088484818181818d6001600160a01b0381166200007657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200008181620001c6565b506001600160a01b038083166080528116620000b057604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b158015620000f857600080fd5b505af11580156200010d573d6000803e3d6000fd5b505050505050505062000125620001c160201b60201c565b60ff168360ff1610156200014c576040516301e9714b60e41b815260040160405180910390fd5b62000159600884620003a0565b6200016690600a620004bf565b60a05250600891506200017c9050838262000568565b5060096200018b828262000568565b5050600c80546001600160a01b0319166001600160a01b03979097169690961790955550620006349a5050505050505050505050565b600890565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200023e57600080fd5b81516001600160401b03808211156200025b576200025b62000216565b604051601f8301601f19908116603f0116810190828211818310171562000286576200028662000216565b8160405283815260209250866020858801011115620002a457600080fd5b600091505b83821015620002c85785820183015181830184015290820190620002a9565b6000602085830101528094505050505092915050565b80516001600160a01b0381168114620002f657600080fd5b919050565b600080600080608085870312156200031257600080fd5b84516001600160401b03808211156200032a57600080fd5b62000338888389016200022c565b955060208701519150808211156200034f57600080fd5b506200035e878288016200022c565b9350506200036f60408601620002de565b91506200037f60608601620002de565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b60ff8281168282160390811115620003bc57620003bc6200038a565b92915050565b600181815b8085111562000403578160001904821115620003e757620003e76200038a565b80851615620003f557918102915b93841c9390800290620003c7565b509250929050565b6000826200041c57506001620003bc565b816200042b57506000620003bc565b81600181146200044457600281146200044f576200046f565b6001915050620003bc565b60ff8411156200046357620004636200038a565b50506001821b620003bc565b5060208310610133831016604e8410600b841016171562000494575081810a620003bc565b620004a08383620003c2565b8060001904821115620004b757620004b76200038a565b029392505050565b6000620004d060ff8416836200040b565b9392505050565b600181811c90821680620004ec57607f821691505b6020821081036200050d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000563576000816000526020600020601f850160051c810160208610156200053e5750805b601f850160051c820191505b818110156200055f578281556001016200054a565b5050505b505050565b81516001600160401b0381111562000584576200058462000216565b6200059c81620005958454620004d7565b8462000513565b602080601f831160018114620005d45760008415620005bb5750858301515b600019600386901b1c1916600185901b1785556200055f565b600085815260208120601f198616915b828110156200060557888601518255948401946001909101908401620005e4565b5085821015620006245787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051613551620006a06000396000818161076101528181611f0101528181611f76015261217a01526000818161060501528181610b2101528181611414015281816116a701528181611a1201528181611d500152818161227b015261233401526135516000f3fe6080604052600436106102c95760003560e01c8063715018a611610175578063bb0b6a53116100dc578063d045a0dc11610095578063e1a452181161006f578063e1a452181461094c578063f2fde38b14610962578063fc0c546a14610569578063ff7bd03d1461098257600080fd5b8063d045a0dc146108d3578063d4243885146108e6578063dd62ed3e1461090657600080fd5b8063bb0b6a5314610817578063bc70b35414610844578063bcae25a414610864578063bd815db01461087f578063c7c7f5b314610892578063ca5eb5e1146108b357600080fd5b8063963efcaa1161012e578063963efcaa1461074f5780639f68b96414610783578063a9059cbb14610797578063b731ea0a146107b7578063b9818be1146107d7578063b98bd070146107f757600080fd5b8063715018a61461069d5780637d25a05e146106b257806382413eac146106ed578063857749b01461046a5780638da5cb5b1461071c57806395d89b411461073a57600080fd5b80633194c180116102345780635535d461116101ed5780635e280f11116101c75780635e280f11146105f35780636db7bcdb146106275780636fc1b31e1461064757806370a082311461066757600080fd5b80635535d4611461057c5780635a0dfe4d1461059c5780635bf9c226146105d357600080fd5b80633194c180146104865780633400288b146104dc5780633b6f743b146104fc5780634488b652146105295780634b104eff1461054957806352ae28791461056957600080fd5b8063156a0d0f11610286578063156a0d0f146103cd57806317442b70146103f457806318160ddd146104165780631f5e13341461043557806323b872dd1461044a578063313ce5671461046a57600080fd5b806306fdde03146102ce578063095ea7b3146102f95780630d35b41514610329578063111ecdad1461035857806313137d6514610390578063134d4f25146103a5575b600080fd5b3480156102da57600080fd5b506102e36109a2565b6040516102f091906125d2565b60405180910390f35b34801561030557600080fd5b506103196103143660046125fa565b610a34565b60405190151581526020016102f0565b34801561033557600080fd5b5061034961034436600461263e565b610a4e565b6040516102f093929190612672565b34801561036457600080fd5b50600454610378906001600160a01b031681565b6040516001600160a01b0390911681526020016102f0565b6103a361039e366004612765565b610b1f565b005b3480156103b157600080fd5b506103ba600281565b60405161ffff90911681526020016102f0565b3480156103d957600080fd5b506040805162b9270b60e21b815260016020820152016102f0565b34801561040057600080fd5b50604080516001815260026020820152016102f0565b34801561042257600080fd5b506007545b6040519081526020016102f0565b34801561044157600080fd5b506103ba600181565b34801561045657600080fd5b50610319610465366004612804565b610bdf565b34801561047657600080fd5b50604051600881526020016102f0565b34801561049257600080fd5b506104c26104a136600461285e565b600b6020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102f0565b3480156104e857600080fd5b506103a36104f7366004612879565b610c05565b34801561050857600080fd5b5061051c6105173660046128a3565b610c1b565b6040516102f091906128f4565b34801561053557600080fd5b506103a361054436600461291d565b610c82565b34801561055557600080fd5b506103a3610564366004612938565b610cfb565b34801561057557600080fd5b5030610378565b34801561058857600080fd5b506102e3610597366004612955565b610d7b565b3480156105a857600080fd5b506103196105b7366004612879565b63ffffffff919091166000908152600160205260409020541490565b3480156105df57600080fd5b506104276105ee366004612879565b610e20565b3480156105ff57600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b34801561063357600080fd5b506103a3610642366004612988565b610e63565b34801561065357600080fd5b506103a3610662366004612938565b610f1f565b34801561067357600080fd5b50610427610682366004612938565b6001600160a01b031660009081526005602052604090205490565b3480156106a957600080fd5b506103a3610f75565b3480156106be57600080fd5b506106d56106cd366004612879565b600092915050565b6040516001600160401b0390911681526020016102f0565b3480156106f957600080fd5b506103196107083660046129cf565b6001600160a01b0381163014949350505050565b34801561072857600080fd5b506000546001600160a01b0316610378565b34801561074657600080fd5b506102e3610f89565b34801561075b57600080fd5b506104277f000000000000000000000000000000000000000000000000000000000000000081565b34801561078f57600080fd5b506000610319565b3480156107a357600080fd5b506103196107b23660046125fa565b610f98565b3480156107c357600080fd5b50600254610378906001600160a01b031681565b3480156107e357600080fd5b50600c54610378906001600160a01b031681565b34801561080357600080fd5b506103a3610812366004612a79565b610fa6565b34801561082357600080fd5b5061042761083236600461285e565b60016020526000908152604090205481565b34801561085057600080fd5b506102e361085f366004612aba565b610fc0565b34801561087057600080fd5b50600a546103ba9061ffff1681565b6103a361088d366004612a79565b611168565b6108a56108a0366004612b1a565b6112f2565b6040516102f0929190612b7c565b3480156108bf57600080fd5b506103a36108ce366004612938565b6113ed565b6103a36108e1366004612765565b611473565b3480156108f257600080fd5b506103a3610901366004612938565b6114a2565b34801561091257600080fd5b50610427610921366004612bce565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b34801561095857600080fd5b506103ba61271081565b34801561096e57600080fd5b506103a361097d366004612938565b6114f8565b34801561098e57600080fd5b5061031961099d366004612bfc565b611536565b6060600880546109b190612c18565b80601f01602080910402602001604051908101604052809291908181526020018280546109dd90612c18565b8015610a2a5780601f106109ff57610100808354040283529160200191610a2a565b820191906000526020600020905b815481529060010190602001808311610a0d57829003601f168201915b5050505050905090565b600033610a4281858561156c565b60019150505b92915050565b60408051808201909152600080825260208201526060610a81604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b03602080840182905284518381529081019094529195509182610adc565b604080518082019091526000815260606020820152815260200190600190039081610ab45790505b509350600080610b01604089013560608a0135610afc60208c018c61285e565b61157e565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610b6f576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610b8990610b84908a61285e565b6115d6565b14610bc757610b9b602088018861285e565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610b66565b610bd687878787878787611612565b50505050505050565b600033610bed858285611779565b610bf88585856117f7565b60019150505b9392505050565b610c0d611856565b610c178282611883565b5050565b60408051808201909152600080825260208201526000610c4b60408501356060860135610afc602088018861285e565b915050600080610c5b86846118d8565b9092509050610c78610c70602088018861285e565b8383886119fc565b9695505050505050565b610c8a611856565b61271061ffff821610610cb05760405163c6cc5d7f60e01b815260040160405180910390fd5b600a805461ffff191661ffff83169081179091556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a150565b610d03611856565b6001600160a01b038116610d2d576040516001628bfb2560e01b0319815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f235247fd708c3a4799d15b30e49e97ff43e74e18a909590c0a9f257a379e19f890602001610cf0565b600360209081526000928352604080842090915290825290208054610d9f90612c18565b80601f0160208091040260200160405190810160405280929190818152602001828054610dcb90612c18565b8015610e185780601f10610ded57610100808354040283529160200191610e18565b820191906000526020600020905b815481529060010190602001808311610dfb57829003601f168201915b505050505081565b600080610e2c84611add565b905061ffff811615610e5857612710610e4961ffff831685612c78565b610e539190612c8f565b610e5b565b60005b949350505050565b610e6b611856565b61271061ffff831610610e915760405163c6cc5d7f60e01b815260040160405180910390fd5b60408051808201825261ffff848116808352841515602080850182815263ffffffff8a166000818152600b84528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201527f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a1505050565b610f27611856565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610cf0565b610f7d611856565b610f876000611b47565b565b6060600980546109b190612c18565b600033610a428185856117f7565b610fae611856565b610c17610fbb8284612d52565b611b97565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610ff490612c18565b80601f016020809104026020016040519081016040528092919081815260200182805461102090612c18565b801561106d5780601f106110425761010080835404028352916020019161106d565b820191906000526020600020905b81548152906001019060200180831161105057829003601f168201915b5050505050905080516000036110bd5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610e5b9350505050565b60008390036110cd579050610e5b565b6002831061114b5761111484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c9e92505050565b806111228460028188612e67565b60405160200161113493929190612e91565b604051602081830303815290604052915050610e5b565b8383604051639a6d49cd60e01b8152600401610b66929190612ee2565b60005b81811015611271573683838381811061118657611186612ef6565b90506020028101906111989190612f0c565b90506111cb6111aa602083018361285e565b602083013563ffffffff919091166000908152600160205260409020541490565b6111d55750611269565b3063d045a0dc60c08301358360a08101356111f4610100830183612f2d565b611205610100890160e08a01612938565b6112136101208a018a612f2d565b6040518963ffffffff1660e01b81526004016112359796959493929190612f88565b6000604051808303818588803b15801561124e57600080fd5b505af1158015611262573d6000803e3d6000fd5b5050505050505b60010161116b565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112b0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112d8919081019061300e565b604051638351eea760e01b8152600401610b6691906125d2565b6112fa61253b565b604080518082019091526000808252602082015260008061133133604089013560608a013561132c60208c018c61285e565b611cca565b9150915060008061134289846118d8565b909250905061136e61135760208b018b61285e565b8383611368368d90038d018d61307b565b8b611d1d565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a906113bc908d018d61285e565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6113f5611856565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b15801561145857600080fd5b505af115801561146c573d6000803e3d6000fd5b5050505050565b3330146114935760405163029a949d60e31b815260040160405180910390fd5b610bd687878787878787610bc7565b6114aa611856565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610cf0565b611500611856565b6001600160a01b03811661152a57604051631e4fbdf760e01b815260006004820152602401610b66565b61153381611b47565b50565b600060208201803590600190839061154e908661285e565b63ffffffff1681526020810191909152604001600020541492915050565b6115798383836001611e28565b505050565b8260008061158c8484610e20565b90506115a061159b82886130ad565b611efd565b9150848210156115cd576040516371c4efed60e01b81526004810183905260248101869052604401610b66565b50935093915050565b63ffffffff811660009081526001602052604081205480610a485760405163f6ff4fb760e01b815263ffffffff84166004820152602401610b66565b60006116246116218787611f34565b90565b905060006116508261163e6116398a8a611f4c565b611f6f565b61164b60208d018d61285e565b611fa4565b9050602886111561171757600061168d61167060608c0160408d016130c0565b61167d60208d018d61285e565b846116888c8c611fcc565b612017565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906116e39086908d9060009087906004016130dd565b600060405180830381600087803b1580156116fd57600080fd5b505af1158015611711573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61175060208d018d61285e565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383811660009081526006602090815260408083209386168352929052205460001981146117f157818110156117e257604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610b66565b6117f184848484036000611e28565b50505050565b6001600160a01b03831661182157604051634b637e8f60e11b815260006004820152602401610b66565b6001600160a01b03821661184b5760405163ec442f0560e01b815260006004820152602401610b66565b611579838383612049565b6000546001600160a01b03163314610f875760405163118cdaa760e01b8152336004820152602401610b66565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061193585602001356118ee86612173565b6118fb60a0890189612f2d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061219f92505050565b909350905060008161194857600161194b565b60025b905061196b61195d602088018861285e565b8261085f60808a018a612f2d565b6004549093506001600160a01b0316156119f3576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb916119b091889188910161310e565b602060405180830381865afa1580156119cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f19190613133565b505b50509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611a5f896115d6565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611a94929190613150565b6040805180830381865afa158015611ab0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad491906131f9565b95945050505050565b63ffffffff81166000908152600b6020908152604080832081518083019092525461ffff8116825262010000900460ff161580159282019290925290611b24575192915050565b600a5461ffff1615611b3e575050600a5461ffff16919050565b50600092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c6e57611bc9828281518110611bb857611bb8612ef6565b602002602001015160400151611c9e565b818181518110611bdb57611bdb612ef6565b60200260200101516040015160036000848481518110611bfd57611bfd612ef6565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c3757611c37612ef6565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c659190613265565b50600101611b9a565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610cf09190613324565b600281015161ffff8116600314610c175781604051639a6d49cd60e01b8152600401610b6691906125d2565b600080611cd885858561157e565b90925090506000611ce982846130ad565b90508015611d0957600c54611d099088906001600160a01b0316836117f7565b611d138783612219565b5094509492505050565b611d2561253b565b6000611d34846000015161224f565b602085015190915015611d4e57611d4e8460200151612277565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611d9e8c6115d6565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611dda929190613150565b60806040518083038185885af1158015611df8573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e1d91906133af565b979650505050505050565b6001600160a01b038416611e525760405163e602df0560e01b815260006004820152602401610b66565b6001600160a01b038316611e7c57604051634a1406b160e11b815260006004820152602401610b66565b6001600160a01b03808516600090815260066020908152604080832093871683529290522082905580156117f157826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611eef91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000611f2a8184612c8f565b610a489190612c78565b6000611f436020828486612e67565b610bfe916133f9565b6000611f5c602860208486612e67565b611f6591613417565b60c01c9392505050565b6000610a487f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416612c78565b60006001600160a01b038416611fba5761dead93505b611fc48484612359565b509092915050565b6060611fdb8260288186612e67565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016120309493929190613447565b6040516020818303038152906040529050949350505050565b6001600160a01b0383166120745780600760008282546120699190613496565b909155506120e69050565b6001600160a01b038316600090815260056020526040902054818110156120c75760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610b66565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b03821661210257600780548290039055612121565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161216691815260200190565b60405180910390a3505050565b6000610a487f000000000000000000000000000000000000000000000000000000000000000083612c8f565b80516060901515806121e85784846040516020016121d492919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405261220f565b848433856040516020016121ff94939291906134a9565b6040516020818303038152906040525b9150935093915050565b6001600160a01b03821661224357604051634b637e8f60e11b815260006004820152602401610b66565b610c1782600083612049565b6000813414612273576040516304fb820960e51b8152346004820152602401610b66565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fb91906134ec565b90506001600160a01b038116612324576040516329b99a9560e11b815260040160405180910390fd5b610c176001600160a01b038216337f00000000000000000000000000000000000000000000000000000000000000008561238f565b6001600160a01b0382166123835760405163ec442f0560e01b815260006004820152602401610b66565b610c1760008383612049565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092019092526020810180516001600160e01b03166323b872dd60e01b1790526117f1918691906000906123f590841683612443565b9050805160001415801561241a5750808060200190518101906124189190613133565b155b1561157957604051635274afe760e01b81526001600160a01b0384166004820152602401610b66565b6060610bfe8383600084600080856001600160a01b031684866040516124699190613509565b60006040518083038185875af1925050503d80600081146124a6576040519150601f19603f3d011682016040523d82523d6000602084013e6124ab565b606091505b5091509150610c788683836060826124cb576124c682612512565b610bfe565b81511580156124e257506001600160a01b0384163b155b1561250b57604051639996b31560e01b81526001600160a01b0385166004820152602401610b66565b5080610bfe565b8051156125225780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180606001604052806000801916815260200160006001600160401b0316815260200161257d604051806040016040528060008152602001600081525090565b905290565b60005b8381101561259d578181015183820152602001612585565b50506000910152565b600081518084526125be816020860160208601612582565b601f01601f19169290920160200192915050565b602081526000610bfe60208301846125a6565b6001600160a01b038116811461153357600080fd5b6000806040838503121561260d57600080fd5b8235612618816125e5565b946020939093013593505050565b600060e0828403121561263857600080fd5b50919050565b60006020828403121561265057600080fd5b81356001600160401b0381111561266657600080fd5b610e5b84828501612626565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b838110156126ed5788870360bf190185528151805188528301518388018790526126da878901826125a6565b97505093820193908201906001016126ae565b50508751606088015250505060208501516080850152509050610e5b565b60006060828403121561263857600080fd5b60008083601f84011261272f57600080fd5b5081356001600160401b0381111561274657600080fd5b60208301915083602082850101111561275e57600080fd5b9250929050565b600080600080600080600060e0888a03121561278057600080fd5b61278a898961270b565b96506060880135955060808801356001600160401b03808211156127ad57600080fd5b6127b98b838c0161271d565b909750955060a08a013591506127ce826125e5565b90935060c089013590808211156127e457600080fd5b506127f18a828b0161271d565b989b979a50959850939692959293505050565b60008060006060848603121561281957600080fd5b8335612824816125e5565b92506020840135612834816125e5565b929592945050506040919091013590565b803563ffffffff8116811461285957600080fd5b919050565b60006020828403121561287057600080fd5b610bfe82612845565b6000806040838503121561288c57600080fd5b61261883612845565b801515811461153357600080fd5b600080604083850312156128b657600080fd5b82356001600160401b038111156128cc57600080fd5b6128d885828601612626565b92505060208301356128e981612895565b809150509250929050565b815181526020808301519082015260408101610a48565b803561ffff8116811461285957600080fd5b60006020828403121561292f57600080fd5b610bfe8261290b565b60006020828403121561294a57600080fd5b8135610bfe816125e5565b6000806040838503121561296857600080fd5b61297183612845565b915061297f6020840161290b565b90509250929050565b60008060006060848603121561299d57600080fd5b6129a684612845565b92506129b46020850161290b565b915060408401356129c481612895565b809150509250925092565b60008060008060a085870312156129e557600080fd5b6129ef868661270b565b935060608501356001600160401b03811115612a0a57600080fd5b612a168782880161271d565b9094509250506080850135612a2a816125e5565b939692955090935050565b60008083601f840112612a4757600080fd5b5081356001600160401b03811115612a5e57600080fd5b6020830191508360208260051b850101111561275e57600080fd5b60008060208385031215612a8c57600080fd5b82356001600160401b03811115612aa257600080fd5b612aae85828601612a35565b90969095509350505050565b60008060008060608587031215612ad057600080fd5b612ad985612845565b9350612ae76020860161290b565b925060408501356001600160401b03811115612b0257600080fd5b612b0e8782880161271d565b95989497509550505050565b60008060008385036080811215612b3057600080fd5b84356001600160401b03811115612b4657600080fd5b612b5287828801612626565b9450506040601f1982011215612b6757600080fd5b5060208401915060608401356129c4816125e5565b600060c082019050835182526001600160401b0360208501511660208301526040840151612bb7604084018280518252602090810151910152565b5082516080830152602083015160a0830152610bfe565b60008060408385031215612be157600080fd5b8235612bec816125e5565b915060208301356128e9816125e5565b600060608284031215612c0e57600080fd5b610bfe838361270b565b600181811c90821680612c2c57607f821691505b60208210810361263857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a4857610a48612c62565b600082612cac57634e487b7160e01b600052601260045260246000fd5b500490565b604051606081016001600160401b0381118282101715612cd357612cd3612c4c565b60405290565b604080519081016001600160401b0381118282101715612cd357612cd3612c4c565b604051601f8201601f191681016001600160401b0381118282101715612d2357612d23612c4c565b604052919050565b60006001600160401b03821115612d4457612d44612c4c565b50601f01601f191660200190565b60006001600160401b0380841115612d6c57612d6c612c4c565b8360051b6020612d7d818301612cfb565b868152918501918181019036841115612d9557600080fd5b865b84811015612e5b57803586811115612daf5760008081fd5b88016060368290031215612dc35760008081fd5b612dcb612cb1565b612dd482612845565b8152612de186830161290b565b8682015260408083013589811115612df95760008081fd5b929092019136601f840112612e0e5760008081fd5b8235612e21612e1c82612d2b565b612cfb565b8181523689838701011115612e365760008081fd5b818986018a830137600091810189019190915290820152845250918301918301612d97565b50979650505050505050565b60008085851115612e7757600080fd5b83861115612e8457600080fd5b5050820193919092039150565b60008451612ea3818460208901612582565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610e5b602083018486612eb9565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612f2357600080fd5b9190910192915050565b6000808335601e19843603018112612f4457600080fd5b8301803591506001600160401b03821115612f5e57600080fd5b60200191503681900382131561275e57600080fd5b6001600160401b038116811461153357600080fd5b63ffffffff612f9689612845565b1681526020880135602082015260006040890135612fb381612f73565b6001600160401b03811660408401525087606083015260e06080830152612fde60e083018789612eb9565b6001600160a01b03861660a084015282810360c0840152613000818587612eb9565b9a9950505050505050505050565b60006020828403121561302057600080fd5b81516001600160401b0381111561303657600080fd5b8201601f8101841361304757600080fd5b8051613055612e1c82612d2b565b81815285602083850101111561306a57600080fd5b611ad4826020830160208601612582565b60006040828403121561308d57600080fd5b613095612cd9565b82358152602083013560208201528091505092915050565b81810381811115610a4857610a48612c62565b6000602082840312156130d257600080fd5b8135610bfe81612f73565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610c7860808301846125a6565b60408152600061312160408301856125a6565b8281036020840152611ad481856125a6565b60006020828403121561314557600080fd5b8151610bfe81612895565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a0608084015261318660e08401826125a6565b90506060850151603f198483030160a08501526131a382826125a6565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156131db57600080fd5b6131e3612cd9565b9050815181526020820151602082015292915050565b60006040828403121561320b57600080fd5b610bfe83836131c9565b601f821115611579576000816000526020600020601f850160051c8101602086101561323e5750805b601f850160051c820191505b8181101561325d5782815560010161324a565b505050505050565b81516001600160401b0381111561327e5761327e612c4c565b6132928161328c8454612c18565b84613215565b602080601f8311600181146132c757600084156132af5750858301515b600019600386901b1c1916600185901b17855561325d565b600085815260208120601f198616915b828110156132f6578886015182559484019460019091019084016132d7565b50858210156133145787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133a157888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261338d818601836125a6565b96890196945050509086019060010161334d565b509098975050505050505050565b6000608082840312156133c157600080fd5b6133c9612cb1565b8251815260208301516133db81612f73565b60208201526133ed84604085016131c9565b60408201529392505050565b80356020831015610a4857600019602084900360031b1b1692915050565b6001600160c01b0319813581811691600885101561343f5780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161348681602c850160208701612582565b91909101602c0195945050505050565b80820180821115610a4857610a48612c62565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516134dc816048850160208701612582565b9190910160480195945050505050565b6000602082840312156134fe57600080fd5b8151610bfe816125e5565b60008251612f2381846020870161258256fea264697066735822122083bf19cec423cd95f6b3986b5b81fc002a263adbd27e353c34ff8a588416d01564736f6c63430008160033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b0000000000000000000000009e175ace5148c5430aa4ce1c0e56856d8df24a89000000000000000000000000000000000000000000000000000000000000000b577261707065642042544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045742544300000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102c95760003560e01c8063715018a611610175578063bb0b6a53116100dc578063d045a0dc11610095578063e1a452181161006f578063e1a452181461094c578063f2fde38b14610962578063fc0c546a14610569578063ff7bd03d1461098257600080fd5b8063d045a0dc146108d3578063d4243885146108e6578063dd62ed3e1461090657600080fd5b8063bb0b6a5314610817578063bc70b35414610844578063bcae25a414610864578063bd815db01461087f578063c7c7f5b314610892578063ca5eb5e1146108b357600080fd5b8063963efcaa1161012e578063963efcaa1461074f5780639f68b96414610783578063a9059cbb14610797578063b731ea0a146107b7578063b9818be1146107d7578063b98bd070146107f757600080fd5b8063715018a61461069d5780637d25a05e146106b257806382413eac146106ed578063857749b01461046a5780638da5cb5b1461071c57806395d89b411461073a57600080fd5b80633194c180116102345780635535d461116101ed5780635e280f11116101c75780635e280f11146105f35780636db7bcdb146106275780636fc1b31e1461064757806370a082311461066757600080fd5b80635535d4611461057c5780635a0dfe4d1461059c5780635bf9c226146105d357600080fd5b80633194c180146104865780633400288b146104dc5780633b6f743b146104fc5780634488b652146105295780634b104eff1461054957806352ae28791461056957600080fd5b8063156a0d0f11610286578063156a0d0f146103cd57806317442b70146103f457806318160ddd146104165780631f5e13341461043557806323b872dd1461044a578063313ce5671461046a57600080fd5b806306fdde03146102ce578063095ea7b3146102f95780630d35b41514610329578063111ecdad1461035857806313137d6514610390578063134d4f25146103a5575b600080fd5b3480156102da57600080fd5b506102e36109a2565b6040516102f091906125d2565b60405180910390f35b34801561030557600080fd5b506103196103143660046125fa565b610a34565b60405190151581526020016102f0565b34801561033557600080fd5b5061034961034436600461263e565b610a4e565b6040516102f093929190612672565b34801561036457600080fd5b50600454610378906001600160a01b031681565b6040516001600160a01b0390911681526020016102f0565b6103a361039e366004612765565b610b1f565b005b3480156103b157600080fd5b506103ba600281565b60405161ffff90911681526020016102f0565b3480156103d957600080fd5b506040805162b9270b60e21b815260016020820152016102f0565b34801561040057600080fd5b50604080516001815260026020820152016102f0565b34801561042257600080fd5b506007545b6040519081526020016102f0565b34801561044157600080fd5b506103ba600181565b34801561045657600080fd5b50610319610465366004612804565b610bdf565b34801561047657600080fd5b50604051600881526020016102f0565b34801561049257600080fd5b506104c26104a136600461285e565b600b6020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102f0565b3480156104e857600080fd5b506103a36104f7366004612879565b610c05565b34801561050857600080fd5b5061051c6105173660046128a3565b610c1b565b6040516102f091906128f4565b34801561053557600080fd5b506103a361054436600461291d565b610c82565b34801561055557600080fd5b506103a3610564366004612938565b610cfb565b34801561057557600080fd5b5030610378565b34801561058857600080fd5b506102e3610597366004612955565b610d7b565b3480156105a857600080fd5b506103196105b7366004612879565b63ffffffff919091166000908152600160205260409020541490565b3480156105df57600080fd5b506104276105ee366004612879565b610e20565b3480156105ff57600080fd5b506103787f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b34801561063357600080fd5b506103a3610642366004612988565b610e63565b34801561065357600080fd5b506103a3610662366004612938565b610f1f565b34801561067357600080fd5b50610427610682366004612938565b6001600160a01b031660009081526005602052604090205490565b3480156106a957600080fd5b506103a3610f75565b3480156106be57600080fd5b506106d56106cd366004612879565b600092915050565b6040516001600160401b0390911681526020016102f0565b3480156106f957600080fd5b506103196107083660046129cf565b6001600160a01b0381163014949350505050565b34801561072857600080fd5b506000546001600160a01b0316610378565b34801561074657600080fd5b506102e3610f89565b34801561075b57600080fd5b506104277f000000000000000000000000000000000000000000000000000000000000000181565b34801561078f57600080fd5b506000610319565b3480156107a357600080fd5b506103196107b23660046125fa565b610f98565b3480156107c357600080fd5b50600254610378906001600160a01b031681565b3480156107e357600080fd5b50600c54610378906001600160a01b031681565b34801561080357600080fd5b506103a3610812366004612a79565b610fa6565b34801561082357600080fd5b5061042761083236600461285e565b60016020526000908152604090205481565b34801561085057600080fd5b506102e361085f366004612aba565b610fc0565b34801561087057600080fd5b50600a546103ba9061ffff1681565b6103a361088d366004612a79565b611168565b6108a56108a0366004612b1a565b6112f2565b6040516102f0929190612b7c565b3480156108bf57600080fd5b506103a36108ce366004612938565b6113ed565b6103a36108e1366004612765565b611473565b3480156108f257600080fd5b506103a3610901366004612938565b6114a2565b34801561091257600080fd5b50610427610921366004612bce565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b34801561095857600080fd5b506103ba61271081565b34801561096e57600080fd5b506103a361097d366004612938565b6114f8565b34801561098e57600080fd5b5061031961099d366004612bfc565b611536565b6060600880546109b190612c18565b80601f01602080910402602001604051908101604052809291908181526020018280546109dd90612c18565b8015610a2a5780601f106109ff57610100808354040283529160200191610a2a565b820191906000526020600020905b815481529060010190602001808311610a0d57829003601f168201915b5050505050905090565b600033610a4281858561156c565b60019150505b92915050565b60408051808201909152600080825260208201526060610a81604051806040016040528060008152602001600081525090565b60408051808201825260008082526001600160401b03602080840182905284518381529081019094529195509182610adc565b604080518082019091526000815260606020820152815260200190600190039081610ab45790505b509350600080610b01604089013560608a0135610afc60208c018c61285e565b61157e565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610b6f576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610b8990610b84908a61285e565b6115d6565b14610bc757610b9b602088018861285e565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610b66565b610bd687878787878787611612565b50505050505050565b600033610bed858285611779565b610bf88585856117f7565b60019150505b9392505050565b610c0d611856565b610c178282611883565b5050565b60408051808201909152600080825260208201526000610c4b60408501356060860135610afc602088018861285e565b915050600080610c5b86846118d8565b9092509050610c78610c70602088018861285e565b8383886119fc565b9695505050505050565b610c8a611856565b61271061ffff821610610cb05760405163c6cc5d7f60e01b815260040160405180910390fd5b600a805461ffff191661ffff83169081179091556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a150565b610d03611856565b6001600160a01b038116610d2d576040516001628bfb2560e01b0319815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f235247fd708c3a4799d15b30e49e97ff43e74e18a909590c0a9f257a379e19f890602001610cf0565b600360209081526000928352604080842090915290825290208054610d9f90612c18565b80601f0160208091040260200160405190810160405280929190818152602001828054610dcb90612c18565b8015610e185780601f10610ded57610100808354040283529160200191610e18565b820191906000526020600020905b815481529060010190602001808311610dfb57829003601f168201915b505050505081565b600080610e2c84611add565b905061ffff811615610e5857612710610e4961ffff831685612c78565b610e539190612c8f565b610e5b565b60005b949350505050565b610e6b611856565b61271061ffff831610610e915760405163c6cc5d7f60e01b815260040160405180910390fd5b60408051808201825261ffff848116808352841515602080850182815263ffffffff8a166000818152600b84528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201527f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a1505050565b610f27611856565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610cf0565b610f7d611856565b610f876000611b47565b565b6060600980546109b190612c18565b600033610a428185856117f7565b610fae611856565b610c17610fbb8284612d52565b611b97565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610ff490612c18565b80601f016020809104026020016040519081016040528092919081815260200182805461102090612c18565b801561106d5780601f106110425761010080835404028352916020019161106d565b820191906000526020600020905b81548152906001019060200180831161105057829003601f168201915b5050505050905080516000036110bd5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610e5b9350505050565b60008390036110cd579050610e5b565b6002831061114b5761111484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c9e92505050565b806111228460028188612e67565b60405160200161113493929190612e91565b604051602081830303815290604052915050610e5b565b8383604051639a6d49cd60e01b8152600401610b66929190612ee2565b60005b81811015611271573683838381811061118657611186612ef6565b90506020028101906111989190612f0c565b90506111cb6111aa602083018361285e565b602083013563ffffffff919091166000908152600160205260409020541490565b6111d55750611269565b3063d045a0dc60c08301358360a08101356111f4610100830183612f2d565b611205610100890160e08a01612938565b6112136101208a018a612f2d565b6040518963ffffffff1660e01b81526004016112359796959493929190612f88565b6000604051808303818588803b15801561124e57600080fd5b505af1158015611262573d6000803e3d6000fd5b5050505050505b60010161116b565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112b0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112d8919081019061300e565b604051638351eea760e01b8152600401610b6691906125d2565b6112fa61253b565b604080518082019091526000808252602082015260008061133133604089013560608a013561132c60208c018c61285e565b611cca565b9150915060008061134289846118d8565b909250905061136e61135760208b018b61285e565b8383611368368d90038d018d61307b565b8b611d1d565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a906113bc908d018d61285e565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6113f5611856565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e190602401600060405180830381600087803b15801561145857600080fd5b505af115801561146c573d6000803e3d6000fd5b5050505050565b3330146114935760405163029a949d60e31b815260040160405180910390fd5b610bd687878787878787610bc7565b6114aa611856565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610cf0565b611500611856565b6001600160a01b03811661152a57604051631e4fbdf760e01b815260006004820152602401610b66565b61153381611b47565b50565b600060208201803590600190839061154e908661285e565b63ffffffff1681526020810191909152604001600020541492915050565b6115798383836001611e28565b505050565b8260008061158c8484610e20565b90506115a061159b82886130ad565b611efd565b9150848210156115cd576040516371c4efed60e01b81526004810183905260248101869052604401610b66565b50935093915050565b63ffffffff811660009081526001602052604081205480610a485760405163f6ff4fb760e01b815263ffffffff84166004820152602401610b66565b60006116246116218787611f34565b90565b905060006116508261163e6116398a8a611f4c565b611f6f565b61164b60208d018d61285e565b611fa4565b9050602886111561171757600061168d61167060608c0160408d016130c0565b61167d60208d018d61285e565b846116888c8c611fcc565b612017565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb59012906116e39086908d9060009087906004016130dd565b600060405180830381600087803b1580156116fd57600080fd5b505af1158015611711573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61175060208d018d61285e565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383811660009081526006602090815260408083209386168352929052205460001981146117f157818110156117e257604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610b66565b6117f184848484036000611e28565b50505050565b6001600160a01b03831661182157604051634b637e8f60e11b815260006004820152602401610b66565b6001600160a01b03821661184b5760405163ec442f0560e01b815260006004820152602401610b66565b611579838383612049565b6000546001600160a01b03163314610f875760405163118cdaa760e01b8152336004820152602401610b66565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061193585602001356118ee86612173565b6118fb60a0890189612f2d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061219f92505050565b909350905060008161194857600161194b565b60025b905061196b61195d602088018861285e565b8261085f60808a018a612f2d565b6004549093506001600160a01b0316156119f3576004805460405163043a78eb60e01b81526001600160a01b039091169163043a78eb916119b091889188910161310e565b602060405180830381865afa1580156119cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f19190613133565b505b50509250929050565b60408051808201909152600080825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611a5f896115d6565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611a94929190613150565b6040805180830381865afa158015611ab0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad491906131f9565b95945050505050565b63ffffffff81166000908152600b6020908152604080832081518083019092525461ffff8116825262010000900460ff161580159282019290925290611b24575192915050565b600a5461ffff1615611b3e575050600a5461ffff16919050565b50600092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c6e57611bc9828281518110611bb857611bb8612ef6565b602002602001015160400151611c9e565b818181518110611bdb57611bdb612ef6565b60200260200101516040015160036000848481518110611bfd57611bfd612ef6565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c3757611c37612ef6565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c659190613265565b50600101611b9a565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610cf09190613324565b600281015161ffff8116600314610c175781604051639a6d49cd60e01b8152600401610b6691906125d2565b600080611cd885858561157e565b90925090506000611ce982846130ad565b90508015611d0957600c54611d099088906001600160a01b0316836117f7565b611d138783612219565b5094509492505050565b611d2561253b565b6000611d34846000015161224f565b602085015190915015611d4e57611d4e8460200151612277565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611d9e8c6115d6565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611dda929190613150565b60806040518083038185885af1158015611df8573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e1d91906133af565b979650505050505050565b6001600160a01b038416611e525760405163e602df0560e01b815260006004820152602401610b66565b6001600160a01b038316611e7c57604051634a1406b160e11b815260006004820152602401610b66565b6001600160a01b03808516600090815260066020908152604080832093871683529290522082905580156117f157826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611eef91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000001611f2a8184612c8f565b610a489190612c78565b6000611f436020828486612e67565b610bfe916133f9565b6000611f5c602860208486612e67565b611f6591613417565b60c01c9392505050565b6000610a487f00000000000000000000000000000000000000000000000000000000000000016001600160401b038416612c78565b60006001600160a01b038416611fba5761dead93505b611fc48484612359565b509092915050565b6060611fdb8260288186612e67565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b6060848484846040516020016120309493929190613447565b6040516020818303038152906040529050949350505050565b6001600160a01b0383166120745780600760008282546120699190613496565b909155506120e69050565b6001600160a01b038316600090815260056020526040902054818110156120c75760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610b66565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b03821661210257600780548290039055612121565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161216691815260200190565b60405180910390a3505050565b6000610a487f000000000000000000000000000000000000000000000000000000000000000183612c8f565b80516060901515806121e85784846040516020016121d492919091825260c01b6001600160c01b031916602082015260280190565b60405160208183030381529060405261220f565b848433856040516020016121ff94939291906134a9565b6040516020818303038152906040525b9150935093915050565b6001600160a01b03821661224357604051634b637e8f60e11b815260006004820152602401610b66565b610c1782600083612049565b6000813414612273576040516304fb820960e51b8152346004820152602401610b66565b5090565b60007f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122fb91906134ec565b90506001600160a01b038116612324576040516329b99a9560e11b815260040160405180910390fd5b610c176001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b8561238f565b6001600160a01b0382166123835760405163ec442f0560e01b815260006004820152602401610b66565b610c1760008383612049565b604080516001600160a01b038581166024830152848116604483015260648083018590528351808403909101815260849092019092526020810180516001600160e01b03166323b872dd60e01b1790526117f1918691906000906123f590841683612443565b9050805160001415801561241a5750808060200190518101906124189190613133565b155b1561157957604051635274afe760e01b81526001600160a01b0384166004820152602401610b66565b6060610bfe8383600084600080856001600160a01b031684866040516124699190613509565b60006040518083038185875af1925050503d80600081146124a6576040519150601f19603f3d011682016040523d82523d6000602084013e6124ab565b606091505b5091509150610c788683836060826124cb576124c682612512565b610bfe565b81511580156124e257506001600160a01b0384163b155b1561250b57604051639996b31560e01b81526001600160a01b0385166004820152602401610b66565b5080610bfe565b8051156125225780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180606001604052806000801916815260200160006001600160401b0316815260200161257d604051806040016040528060008152602001600081525090565b905290565b60005b8381101561259d578181015183820152602001612585565b50506000910152565b600081518084526125be816020860160208601612582565b601f01601f19169290920160200192915050565b602081526000610bfe60208301846125a6565b6001600160a01b038116811461153357600080fd5b6000806040838503121561260d57600080fd5b8235612618816125e5565b946020939093013593505050565b600060e0828403121561263857600080fd5b50919050565b60006020828403121561265057600080fd5b81356001600160401b0381111561266657600080fd5b610e5b84828501612626565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b838110156126ed5788870360bf190185528151805188528301518388018790526126da878901826125a6565b97505093820193908201906001016126ae565b50508751606088015250505060208501516080850152509050610e5b565b60006060828403121561263857600080fd5b60008083601f84011261272f57600080fd5b5081356001600160401b0381111561274657600080fd5b60208301915083602082850101111561275e57600080fd5b9250929050565b600080600080600080600060e0888a03121561278057600080fd5b61278a898961270b565b96506060880135955060808801356001600160401b03808211156127ad57600080fd5b6127b98b838c0161271d565b909750955060a08a013591506127ce826125e5565b90935060c089013590808211156127e457600080fd5b506127f18a828b0161271d565b989b979a50959850939692959293505050565b60008060006060848603121561281957600080fd5b8335612824816125e5565b92506020840135612834816125e5565b929592945050506040919091013590565b803563ffffffff8116811461285957600080fd5b919050565b60006020828403121561287057600080fd5b610bfe82612845565b6000806040838503121561288c57600080fd5b61261883612845565b801515811461153357600080fd5b600080604083850312156128b657600080fd5b82356001600160401b038111156128cc57600080fd5b6128d885828601612626565b92505060208301356128e981612895565b809150509250929050565b815181526020808301519082015260408101610a48565b803561ffff8116811461285957600080fd5b60006020828403121561292f57600080fd5b610bfe8261290b565b60006020828403121561294a57600080fd5b8135610bfe816125e5565b6000806040838503121561296857600080fd5b61297183612845565b915061297f6020840161290b565b90509250929050565b60008060006060848603121561299d57600080fd5b6129a684612845565b92506129b46020850161290b565b915060408401356129c481612895565b809150509250925092565b60008060008060a085870312156129e557600080fd5b6129ef868661270b565b935060608501356001600160401b03811115612a0a57600080fd5b612a168782880161271d565b9094509250506080850135612a2a816125e5565b939692955090935050565b60008083601f840112612a4757600080fd5b5081356001600160401b03811115612a5e57600080fd5b6020830191508360208260051b850101111561275e57600080fd5b60008060208385031215612a8c57600080fd5b82356001600160401b03811115612aa257600080fd5b612aae85828601612a35565b90969095509350505050565b60008060008060608587031215612ad057600080fd5b612ad985612845565b9350612ae76020860161290b565b925060408501356001600160401b03811115612b0257600080fd5b612b0e8782880161271d565b95989497509550505050565b60008060008385036080811215612b3057600080fd5b84356001600160401b03811115612b4657600080fd5b612b5287828801612626565b9450506040601f1982011215612b6757600080fd5b5060208401915060608401356129c4816125e5565b600060c082019050835182526001600160401b0360208501511660208301526040840151612bb7604084018280518252602090810151910152565b5082516080830152602083015160a0830152610bfe565b60008060408385031215612be157600080fd5b8235612bec816125e5565b915060208301356128e9816125e5565b600060608284031215612c0e57600080fd5b610bfe838361270b565b600181811c90821680612c2c57607f821691505b60208210810361263857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a4857610a48612c62565b600082612cac57634e487b7160e01b600052601260045260246000fd5b500490565b604051606081016001600160401b0381118282101715612cd357612cd3612c4c565b60405290565b604080519081016001600160401b0381118282101715612cd357612cd3612c4c565b604051601f8201601f191681016001600160401b0381118282101715612d2357612d23612c4c565b604052919050565b60006001600160401b03821115612d4457612d44612c4c565b50601f01601f191660200190565b60006001600160401b0380841115612d6c57612d6c612c4c565b8360051b6020612d7d818301612cfb565b868152918501918181019036841115612d9557600080fd5b865b84811015612e5b57803586811115612daf5760008081fd5b88016060368290031215612dc35760008081fd5b612dcb612cb1565b612dd482612845565b8152612de186830161290b565b8682015260408083013589811115612df95760008081fd5b929092019136601f840112612e0e5760008081fd5b8235612e21612e1c82612d2b565b612cfb565b8181523689838701011115612e365760008081fd5b818986018a830137600091810189019190915290820152845250918301918301612d97565b50979650505050505050565b60008085851115612e7757600080fd5b83861115612e8457600080fd5b5050820193919092039150565b60008451612ea3818460208901612582565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610e5b602083018486612eb9565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612f2357600080fd5b9190910192915050565b6000808335601e19843603018112612f4457600080fd5b8301803591506001600160401b03821115612f5e57600080fd5b60200191503681900382131561275e57600080fd5b6001600160401b038116811461153357600080fd5b63ffffffff612f9689612845565b1681526020880135602082015260006040890135612fb381612f73565b6001600160401b03811660408401525087606083015260e06080830152612fde60e083018789612eb9565b6001600160a01b03861660a084015282810360c0840152613000818587612eb9565b9a9950505050505050505050565b60006020828403121561302057600080fd5b81516001600160401b0381111561303657600080fd5b8201601f8101841361304757600080fd5b8051613055612e1c82612d2b565b81815285602083850101111561306a57600080fd5b611ad4826020830160208601612582565b60006040828403121561308d57600080fd5b613095612cd9565b82358152602083013560208201528091505092915050565b81810381811115610a4857610a48612c62565b6000602082840312156130d257600080fd5b8135610bfe81612f73565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610c7860808301846125a6565b60408152600061312160408301856125a6565b8281036020840152611ad481856125a6565b60006020828403121561314557600080fd5b8151610bfe81612895565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a0608084015261318660e08401826125a6565b90506060850151603f198483030160a08501526131a382826125a6565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156131db57600080fd5b6131e3612cd9565b9050815181526020820151602082015292915050565b60006040828403121561320b57600080fd5b610bfe83836131c9565b601f821115611579576000816000526020600020601f850160051c8101602086101561323e5750805b601f850160051c820191505b8181101561325d5782815560010161324a565b505050505050565b81516001600160401b0381111561327e5761327e612c4c565b6132928161328c8454612c18565b84613215565b602080601f8311600181146132c757600084156132af5750858301515b600019600386901b1c1916600185901b17855561325d565b600085815260208120601f198616915b828110156132f6578886015182559484019460019091019084016132d7565b50858210156133145787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133a157888303603f190185528151805163ffffffff1684528781015161ffff1688850152860151606087850181905261338d818601836125a6565b96890196945050509086019060010161334d565b509098975050505050505050565b6000608082840312156133c157600080fd5b6133c9612cb1565b8251815260208301516133db81612f73565b60208201526133ed84604085016131c9565b60408201529392505050565b80356020831015610a4857600019602084900360031b1b1692915050565b6001600160c01b0319813581811691600885101561343f5780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161348681602c850160208701612582565b91909101602c0195945050505050565b80820180821115610a4857610a48612c62565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516134dc816048850160208701612582565b9190910160480195945050505050565b6000602082840312156134fe57600080fd5b8151610bfe816125e5565b60008251612f2381846020870161258256fea264697066735822122083bf19cec423cd95f6b3986b5b81fc002a263adbd27e353c34ff8a588416d01564736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b0000000000000000000000009e175ace5148c5430aa4ce1c0e56856d8df24a89000000000000000000000000000000000000000000000000000000000000000b577261707065642042544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045742544300000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Wrapped BTC
Arg [1] : _symbol (string): WBTC
Arg [2] : _lzEndpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
Arg [3] : _owner (address): 0x9E175acE5148c5430aA4ce1C0E56856d8df24A89
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Arg [3] : 0000000000000000000000009e175ace5148c5430aa4ce1c0e56856d8df24a89
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [5] : 5772617070656420425443000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 5742544300000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
99:394:43:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4293:186;;;;;;;;;;-1:-1:-1;4293:186:33;;;;;:::i;:::-;;:::i;:::-;;;1391:14:49;;1384:22;1366:41;;1354:2;1339:18;4293:186:33;1226:187:49;5076:1258:26;;;;;;;;;;-1:-1:-1;5076:1258:26;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2280:27::-;;;;;;;;;;-1:-1:-1;2280:27:26;;;;-1:-1:-1;;;;;2280:27:26;;;;;;-1:-1:-1;;;;;3605:32:49;;;3587:51;;3575:2;3560:18;2280:27:26;3441:203:49;4368:708:2;;;;;;:::i;:::-;;:::i;:::-;;2154:40:26;;;;;;;;;;;;2193:1;2154:40;;;;;5387:6:49;5375:19;;;5357:38;;5345:2;5330:18;2154:40:26;5213:188:49;3425:140:26;;;;;;;;;;-1:-1:-1;3425:140:26;;;-1:-1:-1;;;5576:52:49;;3556:1:26;5659:2:49;5644:18;;5637:59;5549:18;3425:140:26;5406:296:49;1287:235:0;;;;;;;;;;-1:-1:-1;1287:235:0;;;843:1:3;5914:34:49;;678:1:2;5979:2:49;5964:18;;5957:43;5850:18;1287:235:0;5707:299:49;3144:97:33;;;;;;;;;;-1:-1:-1;3222:12:33;;3144:97;;;6157:25:49;;;6145:2;6130:18;3144:97:33;6011:177:49;2117:31:26;;;;;;;;;;;;2147:1;2117:31;;5039:244:33;;;;;;;;;;-1:-1:-1;5039:244:33;;;;;:::i;:::-;;:::i;315:82:43:-;;;;;;;;;;-1:-1:-1;315:82:43;;389:1;6796:36:49;;6784:2;6769:18;315:82:43;6654:184:49;577:56:23;;;;;;;;;;-1:-1:-1;577:56:23;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;7396:6:49;7384:19;;;7366:38;;7447:14;;7440:22;7435:2;7420:18;;7413:50;7339:18;577:56:23;7200:269:49;1724:108:1;;;;;;;;;;-1:-1:-1;1724:108:1;;;;;:::i;:::-;;:::i;6785:774:26:-;;;;;;;;;;-1:-1:-1;6785:774:26;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;730:207:23:-;;;;;;;;;;-1:-1:-1;730:207:23;;;;;:::i;:::-;;:::i;663:196:41:-;;;;;;;;;;-1:-1:-1;663:196:41;;;;;:::i;:::-;;:::i;875:93:9:-;;;;;;;;;;-1:-1:-1;956:4:9;875:93;;538::8;;;;;;;;;;-1:-1:-1;538:93:8;;;;;:::i;:::-;;:::i;14940:132:26:-;;;;;;;;;;-1:-1:-1;14940:132:26;;;;;:::i;:::-;15045:11;;;;;15022:4;15045:11;;;:5;:11;;;;;;:20;;14940:132;1423:201:23;;;;;;;;;;-1:-1:-1;1423:201:23;;;;;:::i;:::-;;:::i;446:46:1:-;;;;;;;;;;;;;;;1055:266:23;;;;;;;;;;-1:-1:-1;1055:266:23;;;;;:::i;:::-;;:::i;4607:163:26:-;;;;;;;;;;-1:-1:-1;4607:163:26;;;;;:::i;:::-;;:::i;3299:116:33:-;;;;;;;;;;-1:-1:-1;3299:116:33;;;;;:::i;:::-;-1:-1:-1;;;;;3390:18:33;3364:7;3390:18;;;:9;:18;;;;;;;3299:116;2293:101:31;;;;;;;;;;;;;:::i;3507:128:2:-;;;;;;;;;;-1:-1:-1;3507:128:2;;;;;:::i;:::-;3596:12;3507:128;;;;;;;;-1:-1:-1;;;;;10745:31:49;;;10727:50;;10715:2;10700:18;3507:128:2;10583:200:49;2013:216:2;;;;;;;;;;-1:-1:-1;2013:216:2;;;;;:::i;:::-;-1:-1:-1;;;;;2198:24:2;;2217:4;2198:24;2013:216;;;;;;;1638:85:31;;;;;;;;;;-1:-1:-1;1684:7:31;1710:6;-1:-1:-1;;;;;1710:6:31;1638:85;;2276:93:33;;;;;;;;;;;;;:::i;1811:46:26:-;;;;;;;;;;;;;;;1460:94:24;;;;;;;;;;-1:-1:-1;1519:4:24;1460:94;;3610:178:33;;;;;;;;;;-1:-1:-1;3610:178:33;;;;;:::i;:::-;;:::i;559:23:9:-;;;;;;;;;;-1:-1:-1;559:23:9;;;;-1:-1:-1;;;;;559:23:9;;;362::41;;;;;;;;;;-1:-1:-1;362:23:41;;;;-1:-1:-1;;;;;362:23:41;;;1391:156:8;;;;;;;;;;-1:-1:-1;1391:156:8;;;;;:::i;:::-;;:::i;569:48:1:-;;;;;;;;;;-1:-1:-1;569:48:1;;;;;:::i;:::-;;;;;;;;;;;;;;3510:981:8;;;;;;;;;;-1:-1:-1;3510:981:8;;;;;:::i;:::-;;:::i;447:27:23:-;;;;;;;;;;-1:-1:-1;447:27:23;;;;;;;;1698:1333:9;;;;;;:::i;:::-;;:::i;8247:1340:26:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;3252:105:1:-;;;;;;;;;;-1:-1:-1;3252:105:1;;;;;:::i;:::-;;:::i;3679:409:9:-;;;;;;:::i;:::-;;:::i;1100:139::-;;;;;;;;;;-1:-1:-1;1100:139:9;;;;;:::i;:::-;;:::i;3846:140:33:-;;;;;;;;;;-1:-1:-1;3846:140:33;;;;;:::i;:::-;-1:-1:-1;;;;;3952:18:33;;;3926:7;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3846:140;312:47:23;;;;;;;;;;;;353:6;312:47;;2543:215:31;;;;;;;;;;-1:-1:-1;2543:215:31;;;;;:::i;:::-;;:::i;2771:149:2:-;;;;;;;;;;-1:-1:-1;2771:149:2;;;;;:::i;:::-;;:::i;2074:89:33:-;2119:13;2151:5;2144:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89;:::o;4293:186::-;4366:4;735:10:39;4420:31:33;735:10:39;4436:7:33;4445:5;4420:8;:31::i;:::-;4468:4;4461:11;;;4293:186;;;;;:::o;5076:1258:26:-;-1:-1:-1;;;;;;;;;;;;;;;;;5228:35:26;5265:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;5265:28:26;5483:34;;;;;;;;-1:-1:-1;5483:34:26;;;-1:-1:-1;;;;;5483:34:26;;;;;;;5634:21;;;;;;;;;;;5483:34;;-1:-1:-1;;;5634:21:26;;;-1:-1:-1;;;;;;;;;;;;;;;;;5634:21:26;;;;;;;;;;;;;;;-1:-1:-1;5618:37:26;-1:-1:-1;6092:20:26;;6142:120;6166:19;;;;6199:22;;;;6235:17;;;;6166:10;6235:17;:::i;:::-;6142:10;:120::i;:::-;6285:42;;;;;;;;;;;;;;;;5076:1258;;;;-1:-1:-1;;;;;;5076:1258:26:o;4368:708:2:-;4681:8;-1:-1:-1;;;;;4673:31:2;4694:10;4673:31;4669:68;;4713:24;;-1:-1:-1;;;4713:24:2;;4726:10;4713:24;;;3587:51:49;3560:18;;4713:24:2;;;;;;;;4669:68;4873:14;;;;;;4837:32;;4854:14;;4873:7;4854:14;:::i;:::-;4837:16;:32::i;:::-;:50;4833:103;;4905:14;;;;:7;:14;:::i;:::-;4896:40;;-1:-1:-1;;;4896:40:2;;16247:10:49;16235:23;;;4896:40:2;;;16217:42:49;4921:14:2;;;;16275:18:49;;;16268:34;16190:18;;4896:40:2;16045:263:49;4833:103:2;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;5039:244:33:-;5126:4;735:10:39;5182:37:33;5198:4;735:10:39;5213:5:33;5182:15;:37::i;:::-;5229:26;5239:4;5245:2;5249:5;5229:9;:26::i;:::-;5272:4;5265:11;;;5039:244;;;;;;:::o;1724:108:1:-;1531:13:31;:11;:13::i;:::-;1804:21:1::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;6785:774:26:-;-1:-1:-1;;;;;;;;;;;;;;;;;7119:24:26;7147:74;7158:19;;;;7179:22;;;;7203:17;;;;7158:10;7203:17;:::i;7147:74::-;7116:105;;;7310:20;7332;7356:49;7376:10;7388:16;7356:19;:49::i;:::-;7309:96;;-1:-1:-1;7309:96:26;-1:-1:-1;7494:58:26;7501:17;;;;:10;:17;:::i;:::-;7520:7;7529;7538:13;7494:6;:58::i;:::-;7487:65;6785:774;-1:-1:-1;;;;;;6785:774:26:o;730:207:23:-;1531:13:31;:11;:13::i;:::-;353:6:23::1;805:26;::::0;::::1;;801:56;;840:17;;-1:-1:-1::0;;;840:17:23::1;;;;;;;;;;;801:56;867:13;:23:::0;;-1:-1:-1;;867:23:23::1;;::::0;::::1;::::0;;::::1;::::0;;;905:25:::1;::::0;5357:38:49;;;905:25:23::1;::::0;5345:2:49;5330:18;905:25:23::1;;;;;;;;730:207:::0;:::o;663:196:41:-;1531:13:31;:11;:13::i;:::-;-1:-1:-1;;;;;736:23:41;::::1;732:53;;768:17;;-1:-1:-1::0;;;;;;768:17:41::1;;;;;;;;;;;732:53;795:8;:20:::0;;-1:-1:-1;;;;;;795:20:41::1;-1:-1:-1::0;;;;;795:20:41;::::1;::::0;;::::1;::::0;;;830:22:::1;::::0;3587:51:49;;;830:22:41::1;::::0;3575:2:49;3560:18;830:22:41::1;3441:203:49::0;538:93:8;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1423:201:23:-;1501:7;1520:10;1533:19;1544:7;1533:10;:19::i;:::-;1520:32;-1:-1:-1;1569:8:23;;;;:48;;353:6;1585:13;1584:33;1585:13;;:7;:13;:::i;:::-;1584:33;;;;:::i;:::-;1569:48;;;1580:1;1569:48;1562:55;1423:201;-1:-1:-1;;;;1423:201:23:o;1055:266::-;1531:13:31;:11;:13::i;:::-;353:6:23::1;1154:26;::::0;::::1;;1150:56;;1189:17;;-1:-1:-1::0;;;1189:17:23::1;;;;;;;;;;;1150:56;1234:28;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;1216:15:::1;::::0;::::1;-1:-1:-1::0;1216:15:23;;;:6:::1;:15:::0;;;;;:46;;;;;;::::1;;::::0;::::1;-1:-1:-1::0;;1216:46:23;;;;::::1;::::0;;;;::::1;::::0;;;1277:37;;17032:42:49;;;17090:18;;;17083:47;17146:18;;;17139:50;1277:37:23::1;::::0;17020:2:49;17005:18;1277:37:23::1;;;;;;;1055:266:::0;;;:::o;4607:163:26:-;1531:13:31;:11;:13::i;:::-;4690:12:26::1;:28:::0;;-1:-1:-1;;;;;;4690:28:26::1;-1:-1:-1::0;;;;;4690:28:26;::::1;::::0;;::::1;::::0;;;4733:30:::1;::::0;3587:51:49;;;4733:30:26::1;::::0;3575:2:49;3560:18;4733:30:26::1;3441:203:49::0;2293:101:31;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;2276:93:33:-;2323:13;2355:7;2348:14;;;;;:::i;3610:178::-;3679:4;735:10:39;3733:27:33;735:10:39;3750:2:33;3754:5;3733:9;:27::i;1391:156:8:-;1531:13:31;:11;:13::i;:::-;1503:37:8::1;;1523:16:::0;;1503:37:::1;:::i;:::-;:19;:37::i;3510:981::-:0;3701:21;;;3677;3701;;;:15;:21;;;;;;;;:31;;;;;;;;;;3677:55;;3653:12;;3677:21;3701:31;3677:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:8;:15;3880:1;3861:20;3857:46;;3890:13;;3883:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3883:20:8;;-1:-1:-1;3883:20:8;;-1:-1:-1;;;;3883:20:8;3857:46;3988:1;3964:25;;;3960:46;;3998:8;-1:-1:-1;3991:15:8;;3960:46;4153:1;4129:25;;4125:267;;4170:34;4190:13;;4170:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4170:19:8;;-1:-1:-1;;;4170:34:8:i;:::-;4353:8;4363:17;:13;4377:1;4363:13;;:17;:::i;:::-;4340:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4333:48;;;;;4125:267;4470:13;;4455:29;;-1:-1:-1;;;4455:29:8;;;;;;;;;:::i;1698:1333:9:-;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:9;1987:20;;;;1854:43;1987:20;:::i;:::-;2009;;;;15045:11:26;;;;;15022:4;15045:11;;;:5;:11;;;;;;:20;;14940:132;1980:50:9;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:9;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2978:45:9;;;;;;;;;;;;:::i;:::-;2961:63;;-1:-1:-1;;;2961:63:9;;;;;;;;:::i;8247:1340:26:-;8408:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;8806:20:26;;8856:140;8876:10;8900:19;;;;8933:22;;;;8969:17;;;;8900:10;8969:17;:::i;:::-;8856:6;:140::i;:::-;8805:191;;;;9085:20;9107;9131:49;9151:10;9163:16;9131:19;:49::i;:::-;9084:96;;-1:-1:-1;9084:96:26;-1:-1:-1;9303:66:26;9311:17;;;;:10;:17;:::i;:::-;9330:7;9339;9303:66;;;;;;;9348:4;9303:66;:::i;:::-;9354:14;9303:7;:66::i;:::-;9435:42;;;;;;;;;;;;;;;;;;;9501:15;;9290:79;;-1:-1:-1;9435:42:26;;-1:-1:-1;9537:10:26;;9501:15;9493:87;;9518:17;;;;:10;:17;:::i;:::-;9493:87;;;25002:10:49;24990:23;;;24972:42;;25045:2;25030:18;;25023:34;;;25073:18;;25066:34;;;24960:2;24945:18;9493:87:26;;;;;;;8474:1113;;;;8247:1340;;;;;;:::o;3252:105:1:-;1531:13:31;:11;:13::i;:::-;3319:31:1::1;::::0;-1:-1:-1;;;3319:31:1;;-1:-1:-1;;;;;3605:32:49;;;3319:31:1::1;::::0;::::1;3587:51:49::0;3319:8:1::1;:20;::::0;::::1;::::0;3560:18:49;;3319:31:1::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3252:105:::0;:::o;3679:409:9:-;3958:10;3980:4;3958:27;3954:50;;3994:10;;-1:-1:-1;;;3994:10:9;;;;;;;;;;;3954:50;4014:67;4033:7;4042:5;4049:8;;4059:9;4070:10;;4014:18;:67::i;1100:139::-;1531:13:31;:11;:13::i;:::-;1175:8:9::1;:20:::0;;-1:-1:-1;;;;;;1175:20:9::1;-1:-1:-1::0;;;;;1175:20:9;::::1;::::0;;::::1;::::0;;;1210:22:::1;::::0;3587:51:49;;;1210:22:9::1;::::0;3575:2:49;3560:18;1210:22:9::1;3441:203:49::0;2543:215:31;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:31;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:31;;2700:1:::1;2672:31;::::0;::::1;3587:51:49::0;3560:18;;2672:31:31::1;3441:203:49::0;2623:91:31::1;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;2771:149:2:-;2853:4;2900:13;;;;;;2876:5;;2853:4;;2882:13;;2900:6;2882:13;:::i;:::-;2876:20;;;;;;;;;;;;;-1:-1:-1;2876:20:2;;:37;;2771:149;-1:-1:-1;;2771:149:2:o;8989:128:33:-;9073:37;9082:5;9089:7;9098:5;9105:4;9073:8;:37::i;:::-;8989:128;;;:::o;865:657:41:-;1085:9;1012:20;;1269:26;1276:7;1085:9;1269:6;:26::i;:::-;1255:40;-1:-1:-1;1324:28:41;1336:15;1255:40;1336:9;:15;:::i;:::-;1324:11;:28::i;:::-;1305:47;;1422:12;1403:16;:31;1399:117;;;1457:48;;-1:-1:-1;;;1457:48:41;;;;;25418:25:49;;;25459:18;;;25452:34;;;25391:18;;1457:48:41;25244:248:49;1399:117:41;1060:462;865:657;;;;;;:::o;2718:196:1:-;2822:11;;;2788:7;2822:11;;;:5;:11;;;;;;;2843:43;;2874:12;;-1:-1:-1;;;2874:12:1;;25671:10:49;25659:23;;2874:12:1;;;25641:42:49;25614:18;;2874:12:1;25497:192:49;11733:1806:26;12210:17;12230:36;:17;:8;;:15;:17::i;:::-;2891:2:30;2780:123;12230:36:26;12210:56;;12399:24;12426:62;12434:9;12445:26;12451:19;:8;;:17;:19::i;:::-;12445:5;:26::i;:::-;12473:14;;;;:7;:14;:::i;:::-;12426:7;:62::i;:::-;12399:89;-1:-1:-1;243:2:30;-1:-1:-1;;12499:955:26;;;12603:23;12629:175;12672:13;;;;;;;;:::i;:::-;12703:14;;;;:7;:14;:::i;:::-;12735:16;12769:21;:8;;:19;:21::i;:::-;12629:25;:175::i;:::-;13351:92;;-1:-1:-1;;;13351:92:26;;12603:201;;-1:-1:-1;;;;;;13351:8:26;:20;;;;:92;;13372:9;;13383:5;;13390:1;;12603:201;;13351:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12526:928;12499:955;-1:-1:-1;;;;;13469:63:26;;13481:5;13469:63;13488:14;;;;:7;:14;:::i;:::-;13469:63;;;16247:10:49;16235:23;;;16217:42;;16290:2;16275:18;;16268:34;;;16190:18;13469:63:26;;;;;;;12036:1503;;11733:1806;;;;;;;:::o;10663:477:33:-;-1:-1:-1;;;;;3952:18:33;;;10762:24;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;10828:37:33;;10824:310;;10904:5;10885:16;:24;10881:130;;;10936:60;;-1:-1:-1;;;10936:60:33;;-1:-1:-1;;;;;26916:32:49;;10936:60:33;;;26898:51:49;26965:18;;;26958:34;;;27008:18;;;27001:34;;;26871:18;;10936:60:33;26696:345:49;10881:130:33;11052:57;11061:5;11068:7;11096:5;11077:16;:24;11103:5;11052:8;:57::i;:::-;10752:388;10663:477;;;:::o;5656:300::-;-1:-1:-1;;;;;5739:18:33;;5735:86;;5780:30;;-1:-1:-1;;;5780:30:33;;5807:1;5780:30;;;3587:51:49;3560:18;;5780:30:33;3441:203:49;5735:86:33;-1:-1:-1;;;;;5834:16:33;;5830:86;;5873:32;;-1:-1:-1;;;5873:32:33;;5902:1;5873:32;;;3587:51:49;3560:18;;5873:32:33;3441:203:49;5830:86:33;5925:24;5933:4;5939:2;5943:5;5925:7;:24::i;1796:162:31:-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:31;735:10:39;1855:23:31;1851:101;;1901:40;;-1:-1:-1;;;1901:40:31;;735:10:39;1901:40:31;;;3587:51:49;3560:18;;1901:40:31;3441:203:49;2286:134:1;2359:11;;;;;;;:5;:11;;;;;;;;;:19;;;2393:20;;16217:42:49;;;16275:18;;16268:34;;;2393:20:1;;16190:18:49;2393:20:1;;;;;;;2286:134;;:::o;9881:1334:26:-;10013:20;10035;10067:15;10238:324;10270:10;:13;;;10297:16;10303:9;10297:5;:16::i;:::-;10531:21;;;;:10;:21;:::i;:::-;10238:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10238:18:26;;-1:-1:-1;;;10238:324:26:i;:::-;10214:348;;-1:-1:-1;10214:348:26;-1:-1:-1;10642:14:26;10214:348;10659:33;;2147:1;10659:33;;;2193:1;10659:33;10642:50;-1:-1:-1;10814:67:26;10829:17;;;;:10;:17;:::i;:::-;10848:7;10857:23;;;;:10;:23;:::i;10814:67::-;11123:12;;10804:77;;-1:-1:-1;;;;;;11123:12:26;:26;11119:89;;11169:12;;;11151:57;;-1:-1:-1;;;11151:57:26;;-1:-1:-1;;;;;11169:12:26;;;;11151:39;;:57;;11191:7;;11200;;11151:57;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;11119:89;10057:1158;;9881: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;1630:291:23:-;1733:15;;;1689:6;1733:15;;;:6;:15;;;;;;;;1707:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1758:139;;1799:13;;1630:291;-1:-1:-1;;1630:291:23:o;1758:139::-;1833:13;;;;:17;1829:68;;-1:-1:-1;;1873:13:23;;;;;1630:291;-1:-1:-1;1630:291:23:o;1829:68::-;-1:-1:-1;1913:1:23;;1630:291;-1:-1:-1;;1630:291:23:o;2912:187:31:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:31;;;-1:-1:-1;;;;;;3020:17:31;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;2237:514:8:-;2345:9;2340:354;2364:16;:23;2360:1;:27;2340:354;;;2522:48;2542:16;2559:1;2542:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2522:19;:48::i;:::-;2656:16;2673:1;2656:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:15;:40;2600:16;2617:1;2600:19;;;;;;;;:::i;:::-;;;;;;;:23;;;2584:40;;;;;;;;;;;;;;;:69;2625:16;2642:1;2625:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:69;;;;;;;;;;;;;;;:99;;;;;;:::i;:::-;-1:-1:-1;2389:3:8;;2340:354;;;;2709:35;2727:16;2709:35;;;;;;:::i;4631:264::-;4801:1;4787:16;;4781:23;4827:28;;;463:1;4827:28;4823:65;;4879:8;4864:24;;-1:-1:-1;;;4864:24:8;;;;;;;;:::i;1528:478:41:-;1689:20;1711:24;1782:44;1793:9;1804:12;1818:7;1782:10;:44::i;:::-;1747:79;;-1:-1:-1;1747:79:41;-1:-1:-1;1836:11:41;1850:31;1747:79;;1850:31;:::i;:::-;1836:45;-1:-1:-1;1895:7:41;;1891:69;;1935:8;;1918:31;;1928:5;;-1:-1:-1;;;;;1935:8:41;1945:3;1918:9;:31::i;:::-;1969:30;1975:5;1982:16;1969:5;:30::i;:::-;1737:269;1528:478;;;;;;;:::o;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;9949:432:33:-;-1:-1:-1;;;;;10061:19:33;;10057:89;;10103:32;;-1:-1:-1;;;10103:32:33;;10132:1;10103:32;;;3587:51:49;3560:18;;10103:32:33;3441:203:49;10057:89:33;-1:-1:-1;;;;;10159:21:33;;10155:90;;10203:31;;-1:-1:-1;;;10203:31:33;;10231:1;10203:31;;;3587:51:49;3560:18;;10203:31:33;3441:203:49;10155:90:33;-1:-1:-1;;;;;10254:18:33;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10299:76;;;;10349:7;-1:-1:-1;;;;;10333:31:33;10342:5;-1:-1:-1;;;;;10333:31:33;;10358:5;10333:31;;;;6157:25:49;;6145:2;6130:18;;6011:177;10333:31:33;;;;;;;;9949:432;;;;:::o;15466:172:26:-;15537:16;15610:21;15573:33;15610:21;15573:9;:33;:::i;:::-;15572:59;;;;:::i;1573:123:30:-;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:30:o;15862:139:26:-;15926:16;15961:33;15973:21;-1:-1:-1;;;;;15961:33:26;;;:::i;2939:462:24:-;3073:24;-1:-1:-1;;;;;3113:19:24;;3109:46;;3148:6;3134:21;;3109:46;3251:21;3257:3;3262:9;3251:5;:21::i;:::-;-1:-1:-1;3385:9:24;;2939:462;-1:-1:-1;;2939:462:24:o;2186:130:30:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:30;;2186:130;-1:-1:-1;;;;;;2186:130:30:o;640:284:29:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;6271:1107:33:-;-1:-1:-1;;;;;6360:18:33;;6356:540;;6512:5;6496:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6356:540:33;;-1:-1:-1;6356:540:33;;-1:-1:-1;;;;;6570:15:33;;6548:19;6570:15;;;:9;:15;;;;;;6603:19;;;6599:115;;;6649:50;;-1:-1:-1;;;6649:50:33;;-1:-1:-1;;;;;26916:32:49;;6649:50:33;;;26898:51:49;26965:18;;;26958:34;;;27008:18;;;27001:34;;;26871:18;;6649:50:33;26696:345:49;6599:115:33;-1:-1:-1;;;;;6834:15:33;;;;;;:9;:15;;;;;6852:19;;;;6834:37;;6356:540;-1:-1:-1;;;;;6910:16:33;;6906:425;;7073:12;:21;;;;;;;6906:425;;;-1:-1:-1;;;;;7284:13:33;;;;;;:9;:13;;;;;:22;;;;;;6906:425;7361:2;-1:-1:-1;;;;;7346:25:33;7355:4;-1:-1:-1;;;;;7346:25:33;;7365:5;7346:25;;;;6157::49;;6145:2;6130:18;;6011:177;7346:25:33;;;;;;;;6271:1107;;;:::o;16225:147:26:-;16290:15;16331:33;16343:21;16331:9;:33;:::i;598:506:30:-;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;34469:19:49;;;34544:3;34522:16;-1:-1:-1;;;;;;34518:51:49;34513:2;34504:12;;34497:73;34595:2;34586:12;;34314:290;1057:40:30;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;8247:206:33:-;-1:-1:-1;;;;;8317:21:33;;8313:89;;8361:30;;-1:-1:-1;;;8361:30:33;;8388:1;8361:30;;;3587:51:49;3560:18;;8361:30:33;3441:203:49;8313:89:33;8411:35;8419:7;8436:1;8440:5;8411:7;:35::i;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:49;6130:18;;4781:26:3;6011:177:49;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;7721:208:33:-;-1:-1:-1;;;;;7791:21:33;;7787:91;;7835:32;;-1:-1:-1;;;7835:32:33;;7864:1;7835:32;;;3587:51:49;3560:18;;7835:32:33;3441:203:49;7787:91:33;7887:35;7903:1;7907:7;7916:5;7887:7;:35::i;1702:188:37:-;1829:53;;;-1:-1:-1;;;;;35660:15:49;;;1829:53:37;;;35642:34:49;35712:15;;;35692:18;;;35685:43;35744:18;;;;35737:34;;;1829:53:37;;;;;;;;;;35577:18:49;;;;1829:53:37;;;;;;;;-1:-1:-1;;;;;1829:53:37;-1:-1:-1;;;1829:53:37;;;1802:81;;1822:5;;1829:53;-1:-1:-1;;4504:33:37;;1844:18;;1829:53;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;-1:-1:-1;;;4631:40:37;;-1:-1:-1;;;;;3605:32:49;;4631:40:37;;;3587:51:49;3560:18;;4631:40:37;3441:203:49;2705:151:38;2780:12;2811:38;2833:6;2841:4;2847:1;2780:12;3421;3435:23;3462:6;-1:-1:-1;;;;;3462:11:38;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:38;;;:23;5045:49;5041:119;;;5121:24;;-1:-1:-1;;;5121:24:38;;-1:-1:-1;;;;;3605:32:49;;5121:24:38;;;3587:51:49;3560:18;;5121:24:38;3441:203:49;5041:119:38;-1:-1:-1;5180:10:38;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:38;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:49:-;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:49;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:49;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:49: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:49;;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:49: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:49;1418:158;-1:-1:-1;1418:158:49: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:49;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:49;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:49;;;;3287:15;;;;2951:1;2944:9;2915:429;;;-1:-1:-1;;2020:12:49;;3426:2;3411:18;;2008:25;-1:-1:-1;;;2082:4:49;2071:16;;2065:23;2049:14;;;2042:47;-1:-1:-1;3361:6:49;-1:-1:-1;3376:54:49;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:49;;-1:-1:-1;;;;;3996:30:49;;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:49;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:49;-1:-1:-1;4881:3:49;4866:19;;4853:33;;-1:-1:-1;4895:31:49;4853:33;4895:31;:::i;:::-;4945:5;;-1:-1:-1;5003:3:49;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:49;;-1:-1:-1;4160:1048:49;;;;5062:86;;-1:-1:-1;;;4160:1048:49: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:49;6505:18;;6492:32;6533:33;6492:32;6533:33;:::i;:::-;6193:456;;6585:7;;-1:-1:-1;;;6639:2:49;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:184::-;7069:6;7122:2;7110:9;7101:7;7097:23;7093:32;7090:52;;;7138:1;7135;7128:12;7090:52;7161:28;7179:9;7161:28;:::i;7474:252::-;7541:6;7549;7602:2;7590:9;7581:7;7577:23;7573:32;7570:52;;;7618:1;7615;7608:12;7570:52;7641:28;7659:9;7641:28;:::i;7731:118::-;7817:5;7810:13;7803:21;7796:5;7793:32;7783:60;;7839:1;7836;7829:12;7854:489;7948:6;7956;8009:2;7997:9;7988:7;7984:23;7980:32;7977:52;;;8025:1;8022;8015:12;7977:52;8065:9;8052:23;-1:-1:-1;;;;;8090:6:49;8087:30;8084:50;;;8130:1;8127;8120:12;8084:50;8153:69;8214:7;8205:6;8194:9;8190:22;8153:69;:::i;:::-;8143:79;;;8272:2;8261:9;8257:18;8244:32;8285:28;8307:5;8285:28;:::i;:::-;8332:5;8322:15;;;7854:489;;;;;:::o;8348:257::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;8542:2;8527:18;;8554:45;1946:149;8610:159;8677:20;;8737:6;8726:18;;8716:29;;8706:57;;8759:1;8756;8749:12;8774:184;8832:6;8885:2;8873:9;8864:7;8860:23;8856:32;8853:52;;;8901:1;8898;8891:12;8853:52;8924:28;8942:9;8924:28;:::i;8963:247::-;9022:6;9075:2;9063:9;9054:7;9050:23;9046:32;9043:52;;;9091:1;9088;9081:12;9043:52;9130:9;9117:23;9149:31;9174:5;9149:31;:::i;9215:256::-;9281:6;9289;9342:2;9330:9;9321:7;9317:23;9313:32;9310:52;;;9358:1;9355;9348:12;9310:52;9381:28;9399:9;9381:28;:::i;:::-;9371:38;;9428:37;9461:2;9450:9;9446:18;9428:37;:::i;:::-;9418:47;;9215:256;;;;;:::o;10193:385::-;10265:6;10273;10281;10334:2;10322:9;10313:7;10309:23;10305:32;10302:52;;;10350:1;10347;10340:12;10302:52;10373:28;10391:9;10373:28;:::i;:::-;10363:38;;10420:37;10453:2;10442:9;10438:18;10420:37;:::i;:::-;10410:47;;10507:2;10496:9;10492:18;10479:32;10520:28;10542:5;10520:28;:::i;:::-;10567:5;10557:15;;;10193:385;;;;;:::o;10788:670::-;10902:6;10910;10918;10926;10979:3;10967:9;10958:7;10954:23;10950:33;10947:53;;;10996:1;10993;10986:12;10947:53;11019;11064:7;11053:9;11019:53;:::i;:::-;11009:63;;11123:2;11112:9;11108:18;11095:32;-1:-1:-1;;;;;11142:6:49;11139:30;11136:50;;;11182:1;11179;11172:12;11136:50;11221:58;11271:7;11262:6;11251:9;11247:22;11221:58;:::i;:::-;11298:8;;-1:-1:-1;11195:84:49;-1:-1:-1;;11383:3:49;11368:19;;11355:33;11397:31;11355:33;11397:31;:::i;:::-;10788:670;;;;-1:-1:-1;10788:670:49;;-1:-1:-1;;10788:670:49:o;11463:395::-;11554:8;11564:6;11618:3;11611:4;11603:6;11599:17;11595:27;11585:55;;11636:1;11633;11626:12;11585:55;-1:-1:-1;11659:20:49;;-1:-1:-1;;;;;11691:30:49;;11688:50;;;11734:1;11731;11724:12;11688:50;11771:4;11763:6;11759:17;11747:29;;11831:3;11824:4;11814:6;11811:1;11807:14;11799:6;11795:27;11791:38;11788:47;11785:67;;;11848:1;11845;11838:12;11863:503;11987:6;11995;12048:2;12036:9;12027:7;12023:23;12019:32;12016:52;;;12064:1;12061;12054:12;12016:52;12104:9;12091:23;-1:-1:-1;;;;;12129:6:49;12126:30;12123:50;;;12169:1;12166;12159:12;12123:50;12208:98;12298:7;12289:6;12278:9;12274:22;12208:98;:::i;:::-;12325:8;;12182:124;;-1:-1:-1;11863:503:49;-1:-1:-1;;;;11863:503:49:o;12553:553::-;12639:6;12647;12655;12663;12716:2;12704:9;12695:7;12691:23;12687:32;12684:52;;;12732:1;12729;12722:12;12684:52;12755:28;12773:9;12755:28;:::i;:::-;12745:38;;12802:37;12835:2;12824:9;12820:18;12802:37;:::i;:::-;12792:47;;12890:2;12879:9;12875:18;12862:32;-1:-1:-1;;;;;12909:6:49;12906:30;12903:50;;;12949:1;12946;12939:12;12903:50;12988:58;13038:7;13029:6;13018:9;13014:22;12988:58;:::i;:::-;12553:553;;;;-1:-1:-1;13065:8:49;-1:-1:-1;;;;12553:553:49:o;13614:657::-;13752:6;13760;13768;13812:9;13803:7;13799:23;13842:3;13838:2;13834:12;13831:32;;;13859:1;13856;13849:12;13831:32;13899:9;13886:23;-1:-1:-1;;;;;13924:6:49;13921:30;13918:50;;;13964:1;13961;13954:12;13918:50;13987:69;14048:7;14039:6;14028:9;14024:22;13987:69;:::i;:::-;13977:79;-1:-1:-1;;14090:2:49;-1:-1:-1;;14072:16:49;;14068:25;14065:45;;;14106:1;14103;14096:12;14065:45;;14144:2;14133:9;14129:18;14119:28;;14197:2;14186:9;14182:18;14169:32;14210:31;14235:5;14210:31;:::i;14276:613::-;14520:4;14562:3;14551:9;14547:19;14539:27;;14599:6;14593:13;14582:9;14575:32;-1:-1:-1;;;;;14667:4:49;14659:6;14655:17;14649:24;14645:49;14638:4;14627:9;14623:20;14616:79;14742:4;14734:6;14730:17;14724:24;14757:62;14813:4;14802:9;14798:20;14784:12;2020;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;2042:47;1946:149;14757:62;-1:-1:-1;2020:12:49;;14878:3;14863:19;;2008:25;2082:4;2071:16;;2065:23;2049:14;;;2042:47;14828:55;1946:149;14894:388;14962:6;14970;15023:2;15011:9;15002:7;14998:23;14994:32;14991:52;;;15039:1;15036;15029:12;14991:52;15078:9;15065:23;15097:31;15122:5;15097:31;:::i;:::-;15147:5;-1:-1:-1;15204:2:49;15189:18;;15176:32;15217:33;15176:32;15217:33;:::i;15287:236::-;15372:6;15425:2;15413:9;15404:7;15400:23;15396:32;15393:52;;;15441:1;15438;15431:12;15393:52;15464:53;15509:7;15498:9;15464:53;:::i;15528:380::-;15607:1;15603:12;;;;15650;;;15671:61;;15725:4;15717:6;15713:17;15703:27;;15671:61;15778:2;15770:6;15767:14;15747:18;15744:38;15741:161;;15824:10;15819:3;15815:20;15812:1;15805:31;15859:4;15856:1;15849:15;15887:4;15884:1;15877:15;15913:127;15974:10;15969:3;15965:20;15962:1;15955:31;16005:4;16002:1;15995:15;16029:4;16026:1;16019:15;16313:127;16374:10;16369:3;16365:20;16362:1;16355:31;16405:4;16402:1;16395:15;16429:4;16426:1;16419:15;16445:168;16518:9;;;16549;;16566:15;;;16560:22;;16546:37;16536:71;;16587:18;;:::i;16618:217::-;16658:1;16684;16674:132;;16728:10;16723:3;16719:20;16716:1;16709:31;16763:4;16760:1;16753:15;16791:4;16788:1;16781:15;16674:132;-1:-1:-1;16820:9:49;;16618:217::o;17200:253::-;17272:2;17266:9;17314:4;17302:17;;-1:-1:-1;;;;;17334:34:49;;17370:22;;;17331:62;17328:88;;;17396:18;;:::i;:::-;17432:2;17425:22;17200:253;:::o;17458:251::-;17530:2;17524:9;;;17560:15;;-1:-1:-1;;;;;17590:34:49;;17626:22;;;17587:62;17584:88;;;17652:18;;:::i;17714:275::-;17785:2;17779:9;17850:2;17831:13;;-1:-1:-1;;17827:27:49;17815:40;;-1:-1:-1;;;;;17870:34:49;;17906:22;;;17867:62;17864:88;;;17932:18;;:::i;:::-;17968:2;17961:22;17714:275;;-1:-1:-1;17714:275:49:o;17994:186::-;18042:4;-1:-1:-1;;;;;18067:6:49;18064:30;18061:56;;;18097:18;;:::i;:::-;-1:-1:-1;18163:2:49;18142:15;-1:-1:-1;;18138:29:49;18169:4;18134:40;;17994:186::o;18185:2115::-;18375:9;-1:-1:-1;;;;;18450:2:49;18442:6;18439:14;18436:40;;;18456:18;;:::i;:::-;18502:6;18499:1;18495:14;18528:4;18552:28;18576:2;18572;18568:11;18552:28;:::i;:::-;18614:19;;;18684:14;;;;18649:12;;;;18721:14;18710:26;;18707:46;;;18749:1;18746;18739:12;18707:46;18773:5;18787:1480;18803:6;18798:3;18795:15;18787:1480;;;18889:3;18876:17;18925:2;18912:11;18909:19;18906:109;;;18969:1;18998:2;18994;18987:14;18906:109;19038:23;;19106:4;19085:14;19081:23;;;19077:34;19074:124;;;19152:1;19181:2;19177;19170:14;19074:124;19226:22;;:::i;:::-;19277:21;19295:2;19277:21;:::i;:::-;19268:7;19261:38;19337:30;19363:2;19359;19355:11;19337:30;:::i;:::-;19332:2;19323:7;19319:16;19312:56;19391:2;19441;19437;19433:11;19420:25;19472:2;19464:6;19461:14;19458:104;;;19516:1;19545:2;19541;19534:14;19458:104;19585:15;;;;;19642:14;19635:4;19627:13;;19623:34;19613:135;;19700:1;19730:3;19725;19718:16;19613:135;19785:2;19772:16;19814:49;19830:32;19858:3;19830:32;:::i;:::-;19814:49;:::i;:::-;19890:3;19883:5;19876:18;19936:14;19931:2;19925:3;19921:2;19917:12;19913:21;19910:41;19907:134;;;19993:1;20023:3;20018;20011:16;19907:134;20096:3;20091:2;20087;20083:11;20078:2;20071:5;20067:14;20054:46;20146:1;20124:15;;;20120:24;;20113:35;;;;20168:16;;;20161:31;20205:20;;-1:-1:-1;20245:12:49;;;;18820;;18787:1480;;;-1:-1:-1;20289:5:49;18185:2115;-1:-1:-1;;;;;;;18185:2115:49:o;20305:331::-;20410:9;20421;20463:8;20451:10;20448:24;20445:44;;;20485:1;20482;20475:12;20445:44;20514:6;20504:8;20501:20;20498:40;;;20534:1;20531;20524:12;20498:40;-1:-1:-1;;20560:23:49;;;20605:25;;;;;-1:-1:-1;20305:331:49:o;20641:476::-;20832:3;20870:6;20864:13;20886:66;20945:6;20940:3;20933:4;20925:6;20921:17;20886:66;:::i;:::-;20974:16;;21027:6;21019;20974:16;20999:35;21091:1;21053:18;;21080:13;;;-1:-1:-1;21053:18:49;;20641:476;-1:-1:-1;;;20641:476:49:o;21122:266::-;21210:6;21205:3;21198:19;21262:6;21255:5;21248:4;21243:3;21239:14;21226:43;-1:-1:-1;21314:1:49;21289:16;;;21307:4;21285:27;;;21278:38;;;;21370:2;21349:15;;;-1:-1:-1;;21345:29:49;21336:39;;;21332:50;;21122:266::o;21393:244::-;21550:2;21539:9;21532:21;21513:4;21570:61;21627:2;21616:9;21612:18;21604:6;21596;21570:61;:::i;21642:127::-;21703:10;21698:3;21694:20;21691:1;21684:31;21734:4;21731:1;21724:15;21758:4;21755:1;21748:15;21774:331;21873:4;21931:11;21918:25;22025:3;22021:8;22010;21994:14;21990:29;21986:44;21966:18;21962:69;21952:97;;22045:1;22042;22035:12;21952:97;22066:33;;;;;21774:331;-1:-1:-1;;21774:331:49:o;22110:521::-;22187:4;22193:6;22253:11;22240:25;22347:2;22343:7;22332:8;22316:14;22312:29;22308:43;22288:18;22284:68;22274:96;;22366:1;22363;22356:12;22274:96;22393:33;;22445:20;;;-1:-1:-1;;;;;;22477:30:49;;22474:50;;;22520:1;22517;22510:12;22474:50;22553:4;22541:17;;-1:-1:-1;22584:14:49;22580:27;;;22570:38;;22567:58;;;22621:1;22618;22611:12;22636:129;-1:-1:-1;;;;;22714:5:49;22710:30;22703:5;22700:41;22690:69;;22755:1;22752;22745:12;22770:992;23148:10;23121:25;23139:6;23121:25;:::i;:::-;23117:42;23106:9;23099:61;23223:4;23215:6;23211:17;23198:31;23191:4;23180:9;23176:20;23169:61;23080:4;23277;23269:6;23265:17;23252:31;23292:30;23316:5;23292:30;:::i;:::-;-1:-1:-1;;;;;23364:5:49;23360:30;23353:4;23342:9;23338:20;23331:60;;23427:6;23422:2;23411:9;23407:18;23400:34;23471:3;23465;23454:9;23450:19;23443:32;23498:62;23555:3;23544:9;23540:19;23532:6;23524;23498:62;:::i;:::-;-1:-1:-1;;;;;23597:32:49;;23617:3;23576:19;;23569:61;23667:22;;;23661:3;23646:19;;23639:51;23707:49;23671:6;23741;23733;23707:49;:::i;:::-;23699:57;22770:992;-1:-1:-1;;;;;;;;;;22770:992:49:o;23767:647::-;23846:6;23899:2;23887:9;23878:7;23874:23;23870:32;23867:52;;;23915:1;23912;23905:12;23867:52;23948:9;23942:16;-1:-1:-1;;;;;23973:6:49;23970:30;23967:50;;;24013:1;24010;24003:12;23967:50;24036:22;;24089:4;24081:13;;24077:27;-1:-1:-1;24067:55:49;;24118:1;24115;24108:12;24067:55;24147:2;24141:9;24172:48;24188:31;24216:2;24188:31;:::i;24172:48::-;24243:2;24236:5;24229:17;24283:7;24278:2;24273;24269;24265:11;24261:20;24258:33;24255:53;;;24304:1;24301;24294:12;24255:53;24317:67;24381:2;24376;24369:5;24365:14;24360:2;24356;24352:11;24317:67;:::i;24419:348::-;24508:6;24561:2;24549:9;24540:7;24536:23;24532:32;24529:52;;;24577:1;24574;24567:12;24529:52;24603:22;;:::i;:::-;24661:9;24648:23;24641:5;24634:38;24732:2;24721:9;24717:18;24704:32;24699:2;24692:5;24688:14;24681:56;24756:5;24746:15;;;24419:348;;;;:::o;25111:128::-;25178:9;;;25199:11;;;25196:37;;;25213:18;;:::i;25694:245::-;25752:6;25805:2;25793:9;25784:7;25780:23;25776:32;25773:52;;;25821:1;25818;25811:12;25773:52;25860:9;25847:23;25879:30;25903:5;25879:30;:::i;25944:479::-;26211:1;26207;26202:3;26198:11;26194:19;26186:6;26182:32;26171:9;26164:51;26251:6;26246:2;26235:9;26231:18;26224:34;26306:6;26298;26294:19;26289:2;26278:9;26274:18;26267:47;26350:3;26345:2;26334:9;26330:18;26323:31;26145:4;26371:46;26412:3;26401:9;26397:19;26389:6;26371:46;:::i;27046:379::-;27239:2;27228:9;27221:21;27202:4;27265:45;27306:2;27295:9;27291:18;27283:6;27265:45;:::i;:::-;27358:9;27350:6;27346:22;27341:2;27330:9;27326:18;27319:50;27386:33;27412:6;27404;27386:33;:::i;27430:245::-;27497:6;27550:2;27538:9;27529:7;27525:23;27521:32;27518:52;;;27566:1;27563;27556:12;27518:52;27598:9;27592:16;27617:28;27639:5;27617:28;:::i;27680:891::-;27903:2;27892:9;27885:21;27961:10;27952:6;27946:13;27942:30;27937:2;27926:9;27922:18;27915:58;28027:4;28019:6;28015:17;28009:24;28004:2;27993:9;27989:18;27982:52;27866:4;28081:2;28073:6;28069:15;28063:22;28122:4;28116:3;28105:9;28101:19;28094:33;28150:52;28197:3;28186:9;28182:19;28168:12;28150:52;:::i;:::-;28136:66;;28251:2;28243:6;28239:15;28233:22;28325:2;28321:7;28309:9;28301:6;28297:22;28293:36;28286:4;28275:9;28271:20;28264:66;28353:41;28387:6;28371:14;28353:41;:::i;:::-;28463:3;28451:16;;;;28445:23;28438:31;28431:39;28425:3;28410:19;;28403:68;-1:-1:-1;;;;;;;;28532:32:49;;;;28525:4;28510:20;;;28503:62;28339:55;27680:891::o;28576:284::-;28646:5;28694:4;28682:9;28677:3;28673:19;28669:30;28666:50;;;28712:1;28709;28702:12;28666:50;28734:22;;:::i;:::-;28725:31;;28785:9;28779:16;28772:5;28765:31;28849:2;28838:9;28834:18;28828:25;28823:2;28816:5;28812:14;28805:49;28576:284;;;;:::o;28865:259::-;28965:6;29018:2;29006:9;28997:7;28993:23;28989:32;28986:52;;;29034:1;29031;29024:12;28986:52;29057:61;29110:7;29099:9;29057:61;:::i;29254:542::-;29355:2;29350:3;29347:11;29344:446;;;29391:1;29415:5;29412:1;29405:16;29459:4;29456:1;29446:18;29529:2;29517:10;29513:19;29510:1;29506:27;29500:4;29496:38;29565:4;29553:10;29550:20;29547:47;;;-1:-1:-1;29588:4:49;29547:47;29643:2;29638:3;29634:12;29631:1;29627:20;29621:4;29617:31;29607:41;;29698:82;29716:2;29709:5;29706:13;29698:82;;;29761:17;;;29742:1;29731:13;29698:82;;;29702:3;;;29254:542;;;:::o;29972:1341::-;30096:3;30090:10;-1:-1:-1;;;;;30115:6:49;30112:30;30109:56;;;30145:18;;:::i;:::-;30174:96;30263:6;30223:38;30255:4;30249:11;30223:38;:::i;:::-;30217:4;30174:96;:::i;:::-;30325:4;;30382:2;30371:14;;30399:1;30394:662;;;;31100:1;31117:6;31114:89;;;-1:-1:-1;31169:19:49;;;31163:26;31114:89;-1:-1:-1;;29929:1:49;29925:11;;;29921:24;29917:29;29907:40;29953:1;29949:11;;;29904:57;31216:81;;30364:943;;30394:662;29201:1;29194:14;;;29238:4;29225:18;;-1:-1:-1;;30430:20:49;;;30547:236;30561:7;30558:1;30555:14;30547:236;;;30650:19;;;30644:26;30629:42;;30742:27;;;;30710:1;30698:14;;;;30577:19;;30547:236;;;30551:3;30811:6;30802:7;30799:19;30796:201;;;30872:19;;;30866:26;-1:-1:-1;;30955:1:49;30951:14;;;30967:3;30947:24;30943:37;30939:42;30924:58;30909:74;;30796:201;-1:-1:-1;;;;;31043:1:49;31027:14;;;31023:22;31010:36;;-1:-1:-1;29972:1341:49:o;31318:1162::-;31532:4;31561:2;31601;31590:9;31586:18;31631:2;31620:9;31613:21;31654:6;31689;31683:13;31720:6;31712;31705:22;31746:2;31736:12;;31779:2;31768:9;31764:18;31757:25;;31841:2;31831:6;31828:1;31824:14;31813:9;31809:30;31805:39;31879:2;31871:6;31867:15;31900:1;31910:541;31924:6;31921:1;31918:13;31910:541;;;31989:22;;;-1:-1:-1;;31985:36:49;31973:49;;32045:13;;32117:9;;32128:10;32113:26;32098:42;;32187:11;;;32181:18;32201:6;32177:31;32160:15;;;32153:56;32248:11;;32242:18;32081:4;32280:15;;;32273:27;;;32323:48;32355:15;;;32242:18;32323:48;:::i;:::-;32429:12;;;;32313:58;-1:-1:-1;;;32394:15:49;;;;31946:1;31939:9;31910:541;;;-1:-1:-1;32468:6:49;;31318:1162;-1:-1:-1;;;;;;;;31318:1162:49:o;32485:525::-;32589:6;32642:3;32630:9;32621:7;32617:23;32613:33;32610:53;;;32659:1;32656;32649:12;32610:53;32685:22;;:::i;:::-;32736:9;32730:16;32723:5;32716:31;32792:2;32781:9;32777:18;32771:25;32805:32;32829:7;32805:32;:::i;:::-;32864:2;32853:14;;32846:31;32909:70;32971:7;32966:2;32951:18;;32909:70;:::i;:::-;32904:2;32893:14;;32886:94;32897:5;32485:525;-1:-1:-1;;;32485:525:49:o;33015:255::-;33135:19;;33174:2;33166:11;;33163:101;;;-1:-1:-1;;33235:2:49;33231:12;;;33228:1;33224:20;33220:33;33209:45;33015:255;;;;:::o;33275:331::-;-1:-1:-1;;;;;;33395:19:49;;33479:11;;;;33510:1;33502:10;;33499:101;;;33587:2;33581;33574:3;33571:1;33567:11;33564:1;33560:19;33556:28;33552:2;33548:37;33544:46;33535:55;;33499:101;;;33275:331;;;;:::o;33611:568::-;-1:-1:-1;;;;;33876:3:49;33872:28;33863:6;33858:3;33854:16;33850:51;33845:3;33838:64;33962:10;33957:3;33953:20;33944:6;33939:3;33935:16;33931:43;33927:1;33922:3;33918:11;33911:64;34005:6;34000:2;33995:3;33991:12;33984:28;33820:3;34041:6;34035:13;34057:75;34125:6;34120:2;34115:3;34111:12;34104:4;34096:6;34092:17;34057:75;:::i;:::-;34152:16;;;;34170:2;34148:25;;33611:568;-1:-1:-1;;;;;33611:568:49:o;34184:125::-;34249:9;;;34270:10;;;34267:36;;;34283:18;;:::i;34609:532::-;34850:6;34845:3;34838:19;-1:-1:-1;;;;;34913:3:49;34909:28;34900:6;34895:3;34891:16;34887:51;34882:2;34877:3;34873:12;34866:73;34969:6;34964:2;34959:3;34955:12;34948:28;34820:3;35005:6;34999:13;35021:73;35087:6;35082:2;35077:3;35073:12;35068:2;35060:6;35056:15;35021:73;:::i;:::-;35114:16;;;;35132:2;35110:25;;34609:532;-1:-1:-1;;;;;34609:532:49:o;35146:251::-;35216:6;35269:2;35257:9;35248:7;35244:23;35240:32;35237:52;;;35285:1;35282;35275:12;35237:52;35317:9;35311:16;35336:31;35361:5;35336:31;:::i;35782:287::-;35911:3;35949:6;35943:13;35965:66;36024:6;36019:3;36012:4;36004:6;36000:17;35965:66;:::i
Swarm Source
ipfs://83bf19cec423cd95f6b3986b5b81fc002a263adbd27e353c34ff8a588416d015
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.