Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- ReceiveUln302
- Optimization enabled
- true
- Compiler version
- v0.8.22+commit.4fc1097e
- Optimization runs
- 20000
- EVM Version
- paris
- Verified at
- 2024-07-21T12:57:43.082589Z
Constructor Arguments
0000000000000000000000001a44076050125825900e736c501f859c50fe728c
Arg [0] (address) : 0x1a44076050125825900e736c501f859c50fe728c
contracts/uln/uln302/ReceiveUln302.sol
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol"; import { SetConfigParam } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol"; import { ILayerZeroEndpointV2, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { IReceiveUlnE2 } from "../interfaces/IReceiveUlnE2.sol"; import { ReceiveUlnBase } from "../ReceiveUlnBase.sol"; import { ReceiveLibBaseE2 } from "../../ReceiveLibBaseE2.sol"; import { UlnConfig } from "../UlnBase.sol"; /// @dev This is a gluing contract. It simply parses the requests and forward to the super.impl() accordingly. /// @dev In this case, it combines the logic of ReceiveUlnBase and ReceiveLibBaseE2 contract ReceiveUln302 is IReceiveUlnE2, ReceiveUlnBase, ReceiveLibBaseE2 { using PacketV1Codec for bytes; /// @dev CONFIG_TYPE_ULN=2 here to align with SendUln302/ReceiveUln302/ReceiveUln301 uint32 internal constant CONFIG_TYPE_ULN = 2; error LZ_ULN_InvalidConfigType(uint32 configType); constructor(address _endpoint) ReceiveLibBaseE2(_endpoint) {} function supportsInterface(bytes4 _interfaceId) public view override returns (bool) { return _interfaceId == type(IReceiveUlnE2).interfaceId || super.supportsInterface(_interfaceId); } // ============================ OnlyEndpoint =================================== // only the ULN config on the receive side function setConfig(address _oapp, SetConfigParam[] calldata _params) external override onlyEndpoint { for (uint256 i = 0; i < _params.length; i++) { SetConfigParam calldata param = _params[i]; _assertSupportedEid(param.eid); if (param.configType == CONFIG_TYPE_ULN) { _setUlnConfig(param.eid, _oapp, abi.decode(param.config, (UlnConfig))); } else { revert LZ_ULN_InvalidConfigType(param.configType); } } } // ============================ External =================================== /// @dev dont need to check endpoint verifiable here to save gas, as it will reverts if not verifiable. function commitVerification(bytes calldata _packetHeader, bytes32 _payloadHash) external { _assertHeader(_packetHeader, localEid); // cache these values to save gas address receiver = _packetHeader.receiverB20(); uint32 srcEid = _packetHeader.srcEid(); UlnConfig memory config = getUlnConfig(receiver, srcEid); _verifyAndReclaimStorage(config, keccak256(_packetHeader), _payloadHash); Origin memory origin = Origin(srcEid, _packetHeader.sender(), _packetHeader.nonce()); // endpoint will revert if nonce <= lazyInboundNonce ILayerZeroEndpointV2(endpoint).verify(origin, receiver, _payloadHash); } /// @dev for dvn to verify the payload function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external { _verify(_packetHeader, _payloadHash, _confirmations); } // ============================ View =================================== function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view override returns (bytes memory) { if (_configType == CONFIG_TYPE_ULN) { return abi.encode(getUlnConfig(_oapp, _eid)); } else { revert LZ_ULN_InvalidConfigType(_configType); } } function isSupportedEid(uint32 _eid) external view override returns (bool) { return _isSupportedEid(_eid); } function version() external pure override returns (uint64 major, uint8 minor, uint8 endpointVersion) { return (3, 0, 2); } }
/contracts/MessageLibBase.sol
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; /// @dev simply a container of endpoint address and local eid abstract contract MessageLibBase { address internal immutable endpoint; uint32 internal immutable localEid; error LZ_MessageLib_OnlyEndpoint(); modifier onlyEndpoint() { if (endpoint != msg.sender) revert LZ_MessageLib_OnlyEndpoint(); _; } constructor(address _endpoint, uint32 _localEid) { endpoint = _endpoint; localEid = _localEid; } }
/contracts/uln/interfaces/IReceiveUlnE2.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @dev should be implemented by the ReceiveUln302 contract and future ReceiveUln contracts on EndpointV2 interface IReceiveUlnE2 { /// @notice for each dvn to verify the payload /// @dev this function signature 0x0223536e function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external; /// @notice verify the payload at endpoint, will check if all DVNs verified function commitVerification(bytes calldata _packetHeader, bytes32 _payloadHash) external; }
/contracts/uln/UlnBase.sol
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; // the formal properties are documented in the setter functions struct UlnConfig { uint64 confirmations; // we store the length of required DVNs and optional DVNs instead of using DVN.length directly to save gas uint8 requiredDVNCount; // 0 indicate DEFAULT, NIL_DVN_COUNT indicate NONE (to override the value of default) uint8 optionalDVNCount; // 0 indicate DEFAULT, NIL_DVN_COUNT indicate NONE (to override the value of default) uint8 optionalDVNThreshold; // (0, optionalDVNCount] address[] requiredDVNs; // no duplicates. sorted an an ascending order. allowed overlap with optionalDVNs address[] optionalDVNs; // no duplicates. sorted an an ascending order. allowed overlap with requiredDVNs } struct SetDefaultUlnConfigParam { uint32 eid; UlnConfig config; } /// @dev includes the utility functions for checking ULN states and logics abstract contract UlnBase is Ownable { address private constant DEFAULT_CONFIG = address(0); // reserved values for uint8 internal constant DEFAULT = 0; uint8 internal constant NIL_DVN_COUNT = type(uint8).max; uint64 internal constant NIL_CONFIRMATIONS = type(uint64).max; // 127 to prevent total number of DVNs (127 * 2) exceeding uint8.max (255) // by limiting the total size, it would help constraint the design of DVNOptions uint8 private constant MAX_COUNT = (type(uint8).max - 1) / 2; mapping(address oapp => mapping(uint32 eid => UlnConfig)) internal ulnConfigs; error LZ_ULN_Unsorted(); error LZ_ULN_InvalidRequiredDVNCount(); error LZ_ULN_InvalidOptionalDVNCount(); error LZ_ULN_AtLeastOneDVN(); error LZ_ULN_InvalidOptionalDVNThreshold(); error LZ_ULN_InvalidConfirmations(); error LZ_ULN_UnsupportedEid(uint32 eid); event DefaultUlnConfigsSet(SetDefaultUlnConfigParam[] params); event UlnConfigSet(address oapp, uint32 eid, UlnConfig config); // ============================ OnlyOwner =================================== /// @dev about the DEFAULT ULN config /// 1) its values are all LITERAL (e.g. 0 is 0). whereas in the oapp ULN config, 0 (default value) points to the default ULN config /// this design enables the oapp to point to DEFAULT config without explicitly setting the config /// 2) its configuration is more restrictive than the oapp ULN config that /// a) it must not use NIL value, where NIL is used only by oapps to indicate the LITERAL 0 /// b) it must have at least one DVN function setDefaultUlnConfigs(SetDefaultUlnConfigParam[] calldata _params) external onlyOwner { for (uint256 i = 0; i < _params.length; ++i) { SetDefaultUlnConfigParam calldata param = _params[i]; // 2.a must not use NIL if (param.config.requiredDVNCount == NIL_DVN_COUNT) revert LZ_ULN_InvalidRequiredDVNCount(); if (param.config.optionalDVNCount == NIL_DVN_COUNT) revert LZ_ULN_InvalidOptionalDVNCount(); if (param.config.confirmations == NIL_CONFIRMATIONS) revert LZ_ULN_InvalidConfirmations(); // 2.b must have at least one dvn _assertAtLeastOneDVN(param.config); _setConfig(DEFAULT_CONFIG, param.eid, param.config); } emit DefaultUlnConfigsSet(_params); } // ============================ View =================================== // @dev assuming most oapps use default, we get default as memory and custom as storage to save gas function getUlnConfig(address _oapp, uint32 _remoteEid) public view returns (UlnConfig memory rtnConfig) { UlnConfig storage defaultConfig = ulnConfigs[DEFAULT_CONFIG][_remoteEid]; UlnConfig storage customConfig = ulnConfigs[_oapp][_remoteEid]; // if confirmations is 0, use default uint64 confirmations = customConfig.confirmations; if (confirmations == DEFAULT) { rtnConfig.confirmations = defaultConfig.confirmations; } else if (confirmations != NIL_CONFIRMATIONS) { // if confirmations is uint64.max, no block confirmations required rtnConfig.confirmations = confirmations; } // else do nothing, rtnConfig.confirmation is 0 if (customConfig.requiredDVNCount == DEFAULT) { if (defaultConfig.requiredDVNCount > 0) { // copy only if count > 0. save gas rtnConfig.requiredDVNs = defaultConfig.requiredDVNs; rtnConfig.requiredDVNCount = defaultConfig.requiredDVNCount; } // else, do nothing } else { if (customConfig.requiredDVNCount != NIL_DVN_COUNT) { rtnConfig.requiredDVNs = customConfig.requiredDVNs; rtnConfig.requiredDVNCount = customConfig.requiredDVNCount; } // else, do nothing } if (customConfig.optionalDVNCount == DEFAULT) { if (defaultConfig.optionalDVNCount > 0) { // copy only if count > 0. save gas rtnConfig.optionalDVNs = defaultConfig.optionalDVNs; rtnConfig.optionalDVNCount = defaultConfig.optionalDVNCount; rtnConfig.optionalDVNThreshold = defaultConfig.optionalDVNThreshold; } } else { if (customConfig.optionalDVNCount != NIL_DVN_COUNT) { rtnConfig.optionalDVNs = customConfig.optionalDVNs; rtnConfig.optionalDVNCount = customConfig.optionalDVNCount; rtnConfig.optionalDVNThreshold = customConfig.optionalDVNThreshold; } } // the final value must have at least one dvn // it is possible that some default config result into 0 dvns _assertAtLeastOneDVN(rtnConfig); } /// @dev Get the uln config without the default config for the given remoteEid. function getAppUlnConfig(address _oapp, uint32 _remoteEid) external view returns (UlnConfig memory) { return ulnConfigs[_oapp][_remoteEid]; } // ============================ Internal =================================== function _setUlnConfig(uint32 _remoteEid, address _oapp, UlnConfig memory _param) internal { _setConfig(_oapp, _remoteEid, _param); // get ULN config again as a catch all to ensure the config is valid getUlnConfig(_oapp, _remoteEid); emit UlnConfigSet(_oapp, _remoteEid, _param); } /// @dev a supported Eid must have a valid default uln config, which has at least one dvn function _isSupportedEid(uint32 _remoteEid) internal view returns (bool) { UlnConfig storage defaultConfig = ulnConfigs[DEFAULT_CONFIG][_remoteEid]; return defaultConfig.requiredDVNCount > 0 || defaultConfig.optionalDVNThreshold > 0; } function _assertSupportedEid(uint32 _remoteEid) internal view { if (!_isSupportedEid(_remoteEid)) revert LZ_ULN_UnsupportedEid(_remoteEid); } // ============================ Private =================================== function _assertAtLeastOneDVN(UlnConfig memory _config) private pure { if (_config.requiredDVNCount == 0 && _config.optionalDVNThreshold == 0) revert LZ_ULN_AtLeastOneDVN(); } /// @dev this private function is used in both setDefaultUlnConfigs and setUlnConfig function _setConfig(address _oapp, uint32 _eid, UlnConfig memory _param) private { // @dev required dvns // if dvnCount == NONE, dvns list must be empty // if dvnCount == DEFAULT, dvn list must be empty // otherwise, dvnList.length == dvnCount and assert the list is valid if (_param.requiredDVNCount == NIL_DVN_COUNT || _param.requiredDVNCount == DEFAULT) { if (_param.requiredDVNs.length != 0) revert LZ_ULN_InvalidRequiredDVNCount(); } else { if (_param.requiredDVNs.length != _param.requiredDVNCount || _param.requiredDVNCount > MAX_COUNT) revert LZ_ULN_InvalidRequiredDVNCount(); _assertNoDuplicates(_param.requiredDVNs); } // @dev optional dvns // if optionalDVNCount == NONE, optionalDVNs list must be empty and threshold must be 0 // if optionalDVNCount == DEFAULT, optionalDVNs list must be empty and threshold must be 0 // otherwise, optionalDVNs.length == optionalDVNCount, threshold > 0 && threshold <= optionalDVNCount and assert the list is valid // example use case: an oapp uses the DEFAULT 'required' but // a) use a custom 1/1 dvn (practically a required dvn), or // b) use a custom 2/3 dvn if (_param.optionalDVNCount == NIL_DVN_COUNT || _param.optionalDVNCount == DEFAULT) { if (_param.optionalDVNs.length != 0) revert LZ_ULN_InvalidOptionalDVNCount(); if (_param.optionalDVNThreshold != 0) revert LZ_ULN_InvalidOptionalDVNThreshold(); } else { if (_param.optionalDVNs.length != _param.optionalDVNCount || _param.optionalDVNCount > MAX_COUNT) revert LZ_ULN_InvalidOptionalDVNCount(); if (_param.optionalDVNThreshold == 0 || _param.optionalDVNThreshold > _param.optionalDVNCount) revert LZ_ULN_InvalidOptionalDVNThreshold(); _assertNoDuplicates(_param.optionalDVNs); } // don't assert valid count here, as it needs to be validated along side default config ulnConfigs[_oapp][_eid] = _param; } function _assertNoDuplicates(address[] memory _dvns) private pure { address lastDVN = address(0); for (uint256 i = 0; i < _dvns.length; i++) { address dvn = _dvns[i]; if (dvn <= lastDVN) revert LZ_ULN_Unsorted(); // to ensure no duplicates lastDVN = dvn; } } }
/contracts/uln/ReceiveUlnBase.sol
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol"; import { UlnBase, UlnConfig } from "./UlnBase.sol"; struct Verification { bool submitted; uint64 confirmations; } /// @dev includes the utility functions for checking ULN states and logics abstract contract ReceiveUlnBase is UlnBase { using PacketV1Codec for bytes; mapping(bytes32 headerHash => mapping(bytes32 payloadHash => mapping(address dvn => Verification))) public hashLookup; event PayloadVerified(address dvn, bytes header, uint256 confirmations, bytes32 proofHash); error LZ_ULN_InvalidPacketHeader(); error LZ_ULN_InvalidPacketVersion(); error LZ_ULN_InvalidEid(); error LZ_ULN_Verifying(); // ============================ External =================================== function verifiable( UlnConfig memory _config, bytes32 _headerHash, bytes32 _payloadHash ) external view returns (bool) { return _checkVerifiable(_config, _headerHash, _payloadHash); } function assertHeader(bytes calldata _packetHeader, uint32 _localEid) external pure { _assertHeader(_packetHeader, _localEid); } // ============================ Internal =================================== /// @dev per DVN signing function function _verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) internal { hashLookup[keccak256(_packetHeader)][_payloadHash][msg.sender] = Verification(true, _confirmations); emit PayloadVerified(msg.sender, _packetHeader, _confirmations, _payloadHash); } function _verified( address _dvn, bytes32 _headerHash, bytes32 _payloadHash, uint64 _requiredConfirmation ) internal view returns (bool verified) { Verification memory verification = hashLookup[_headerHash][_payloadHash][_dvn]; // return true if the dvn has signed enough confirmations verified = verification.submitted && verification.confirmations >= _requiredConfirmation; } function _verifyAndReclaimStorage(UlnConfig memory _config, bytes32 _headerHash, bytes32 _payloadHash) internal { if (!_checkVerifiable(_config, _headerHash, _payloadHash)) { revert LZ_ULN_Verifying(); } // iterate the required DVNs if (_config.requiredDVNCount > 0) { for (uint8 i = 0; i < _config.requiredDVNCount; ++i) { delete hashLookup[_headerHash][_payloadHash][_config.requiredDVNs[i]]; } } // iterate the optional DVNs if (_config.optionalDVNCount > 0) { for (uint8 i = 0; i < _config.optionalDVNCount; ++i) { delete hashLookup[_headerHash][_payloadHash][_config.optionalDVNs[i]]; } } } function _assertHeader(bytes calldata _packetHeader, uint32 _localEid) internal pure { // assert packet header is of right size 81 if (_packetHeader.length != 81) revert LZ_ULN_InvalidPacketHeader(); // assert packet header version is the same as ULN if (_packetHeader.version() != PacketV1Codec.PACKET_VERSION) revert LZ_ULN_InvalidPacketVersion(); // assert the packet is for this endpoint if (_packetHeader.dstEid() != _localEid) revert LZ_ULN_InvalidEid(); } /// @dev for verifiable view function /// @dev checks if this verification is ready to be committed to the endpoint function _checkVerifiable( UlnConfig memory _config, bytes32 _headerHash, bytes32 _payloadHash ) internal view returns (bool) { // iterate the required DVNs if (_config.requiredDVNCount > 0) { for (uint8 i = 0; i < _config.requiredDVNCount; ++i) { if (!_verified(_config.requiredDVNs[i], _headerHash, _payloadHash, _config.confirmations)) { // return if any of the required DVNs haven't signed return false; } } if (_config.optionalDVNCount == 0) { // returns early if all required DVNs have signed and there are no optional DVNs return true; } } // then it must require optional validations uint8 threshold = _config.optionalDVNThreshold; for (uint8 i = 0; i < _config.optionalDVNCount; ++i) { if (_verified(_config.optionalDVNs[i], _headerHash, _payloadHash, _config.confirmations)) { // increment the optional count if the optional DVN has signed threshold--; if (threshold == 0) { // early return if the optional threshold has hit return true; } } } // return false as a catch-all return false; } }
/contracts/ReceiveLibBaseE2.sol
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { ILayerZeroEndpointV2, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { IMessageLib, MessageLibType } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol"; import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol"; import { MessageLibBase } from "./MessageLibBase.sol"; /// @dev receive-side message library base contract on endpoint v2. /// it does not have the complication as the one of endpoint v1, such as nonce, executor whitelist, etc. abstract contract ReceiveLibBaseE2 is MessageLibBase, ERC165, IMessageLib { using PacketV1Codec for bytes; constructor(address _endpoint) MessageLibBase(_endpoint, ILayerZeroEndpointV2(_endpoint).eid()) {} function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return _interfaceId == type(IMessageLib).interfaceId || super.supportsInterface(_interfaceId); } function messageLibType() external pure virtual override returns (MessageLibType) { return MessageLibType.Receive; } }
/@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
/@openzeppelin/contracts/utils/introspection/ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
/@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
/@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @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 { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _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); } }
/@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol
// 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)); } }
/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol
// 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)); } }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol
// 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; }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol
// 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); }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol
// 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; }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol
// 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); }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; struct SetConfigParam { uint32 eid; uint32 configType; bytes config; } interface IMessageLibManager { struct Timeout { address lib; uint256 expiry; } event LibraryRegistered(address newLib); event DefaultSendLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry); event SendLibrarySet(address sender, uint32 eid, address newLib); event ReceiveLibrarySet(address receiver, uint32 eid, address newLib); event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout); function registerLibrary(address _lib) external; function isRegisteredLibrary(address _lib) external view returns (bool); function getRegisteredLibraries() external view returns (address[] memory); function setDefaultSendLibrary(uint32 _eid, address _newLib) external; function defaultSendLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol
// 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); }
/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { IMessageLibManager } from "./IMessageLibManager.sol"; import { IMessagingComposer } from "./IMessagingComposer.sol"; import { IMessagingChannel } from "./IMessagingChannel.sol"; import { IMessagingContext } from "./IMessagingContext.sol"; struct MessagingParams { uint32 dstEid; bytes32 receiver; bytes message; bytes options; bool payInLzToken; } struct MessagingReceipt { bytes32 guid; uint64 nonce; MessagingFee fee; } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } struct Origin { uint32 srcEid; bytes32 sender; uint64 nonce; } interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext { event PacketSent(bytes encodedPayload, bytes options, address sendLibrary); event PacketVerified(Origin origin, address receiver, bytes32 payloadHash); event PacketDelivered(Origin origin, address receiver); event LzReceiveAlert( address indexed receiver, address indexed executor, Origin origin, bytes32 guid, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); event LzTokenSet(address token); event DelegateSet(address sender, address delegate); function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory); function send( MessagingParams calldata _params, address _refundAddress ) external payable returns (MessagingReceipt memory); function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external; function verifiable(Origin calldata _origin, address _receiver) external view returns (bool); function initializable(Origin calldata _origin, address _receiver) external view returns (bool); function lzReceive( Origin calldata _origin, address _receiver, bytes32 _guid, bytes calldata _message, bytes calldata _extraData ) external payable; // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external; function setLzToken(address _lzToken) external; function lzToken() external view returns (address); function nativeToken() external view returns (address); function setDelegate(address _delegate) external; }
Compiler Settings
{"remappings":[],"optimizer":{"runs":20000,"enabled":true},"metadata":{"useLiteralContent":true,"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"contracts/uln/uln302/ReceiveUln302.sol":"ReceiveUln302"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_endpoint","internalType":"address"}]},{"type":"error","name":"LZ_MessageLib_OnlyEndpoint","inputs":[]},{"type":"error","name":"LZ_ULN_AtLeastOneDVN","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidConfigType","inputs":[{"type":"uint32","name":"configType","internalType":"uint32"}]},{"type":"error","name":"LZ_ULN_InvalidConfirmations","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidEid","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidOptionalDVNCount","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidOptionalDVNThreshold","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidPacketHeader","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidPacketVersion","inputs":[]},{"type":"error","name":"LZ_ULN_InvalidRequiredDVNCount","inputs":[]},{"type":"error","name":"LZ_ULN_Unsorted","inputs":[]},{"type":"error","name":"LZ_ULN_UnsupportedEid","inputs":[{"type":"uint32","name":"eid","internalType":"uint32"}]},{"type":"error","name":"LZ_ULN_Verifying","inputs":[]},{"type":"event","name":"DefaultUlnConfigsSet","inputs":[{"type":"tuple[]","name":"params","internalType":"struct SetDefaultUlnConfigParam[]","indexed":false,"components":[{"type":"uint32","name":"eid","internalType":"uint32"},{"type":"tuple","name":"config","internalType":"struct UlnConfig","components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]}]}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PayloadVerified","inputs":[{"type":"address","name":"dvn","internalType":"address","indexed":false},{"type":"bytes","name":"header","internalType":"bytes","indexed":false},{"type":"uint256","name":"confirmations","internalType":"uint256","indexed":false},{"type":"bytes32","name":"proofHash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"UlnConfigSet","inputs":[{"type":"address","name":"oapp","internalType":"address","indexed":false},{"type":"uint32","name":"eid","internalType":"uint32","indexed":false},{"type":"tuple","name":"config","internalType":"struct UlnConfig","indexed":false,"components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]}],"anonymous":false},{"type":"function","stateMutability":"pure","outputs":[],"name":"assertHeader","inputs":[{"type":"bytes","name":"_packetHeader","internalType":"bytes"},{"type":"uint32","name":"_localEid","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"commitVerification","inputs":[{"type":"bytes","name":"_packetHeader","internalType":"bytes"},{"type":"bytes32","name":"_payloadHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct UlnConfig","components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]}],"name":"getAppUlnConfig","inputs":[{"type":"address","name":"_oapp","internalType":"address"},{"type":"uint32","name":"_remoteEid","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"getConfig","inputs":[{"type":"uint32","name":"_eid","internalType":"uint32"},{"type":"address","name":"_oapp","internalType":"address"},{"type":"uint32","name":"_configType","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"rtnConfig","internalType":"struct UlnConfig","components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]}],"name":"getUlnConfig","inputs":[{"type":"address","name":"_oapp","internalType":"address"},{"type":"uint32","name":"_remoteEid","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"submitted","internalType":"bool"},{"type":"uint64","name":"confirmations","internalType":"uint64"}],"name":"hashLookup","inputs":[{"type":"bytes32","name":"headerHash","internalType":"bytes32"},{"type":"bytes32","name":"payloadHash","internalType":"bytes32"},{"type":"address","name":"dvn","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isSupportedEid","inputs":[{"type":"uint32","name":"_eid","internalType":"uint32"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"enum MessageLibType"}],"name":"messageLibType","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setConfig","inputs":[{"type":"address","name":"_oapp","internalType":"address"},{"type":"tuple[]","name":"_params","internalType":"struct SetConfigParam[]","components":[{"type":"uint32","name":"eid","internalType":"uint32"},{"type":"uint32","name":"configType","internalType":"uint32"},{"type":"bytes","name":"config","internalType":"bytes"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDefaultUlnConfigs","inputs":[{"type":"tuple[]","name":"_params","internalType":"struct SetDefaultUlnConfigParam[]","components":[{"type":"uint32","name":"eid","internalType":"uint32"},{"type":"tuple","name":"config","internalType":"struct UlnConfig","components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"_interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"verifiable","inputs":[{"type":"tuple","name":"_config","internalType":"struct UlnConfig","components":[{"type":"uint64","name":"confirmations","internalType":"uint64"},{"type":"uint8","name":"requiredDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNCount","internalType":"uint8"},{"type":"uint8","name":"optionalDVNThreshold","internalType":"uint8"},{"type":"address[]","name":"requiredDVNs","internalType":"address[]"},{"type":"address[]","name":"optionalDVNs","internalType":"address[]"}]},{"type":"bytes32","name":"_headerHash","internalType":"bytes32"},{"type":"bytes32","name":"_payloadHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"verify","inputs":[{"type":"bytes","name":"_packetHeader","internalType":"bytes"},{"type":"bytes32","name":"_payloadHash","internalType":"bytes32"},{"type":"uint64","name":"_confirmations","internalType":"uint64"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint64","name":"major","internalType":"uint64"},{"type":"uint8","name":"minor","internalType":"uint8"},{"type":"uint8","name":"endpointVersion","internalType":"uint8"}],"name":"version","inputs":[]}]
Contract Creation Code
0x60c06040523480156200001157600080fd5b5060405162002c9f38038062002c9f833981016040819052620000349162000116565b8080816001600160a01b031663416ecebf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b919062000148565b620000a633620000c6565b6001600160a01b0390911660805263ffffffff1660a05250620001709050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156200012957600080fd5b81516001600160a01b03811681146200014157600080fd5b9392505050565b6000602082840312156200015b57600080fd5b815163ffffffff811681146200014157600080fd5b60805160a051612b026200019d600039600061036e01526000818161049201526104fb0152612b026000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806343ea4fa9116100b25780638da5cb5b11610081578063c40ff83511610066578063c40ff835146102c0578063e084d952146102d3578063f2fde38b146102e657600080fd5b80638da5cb5b146102785780639c33abf7146102a057600080fd5b806343ea4fa91461022a57806354fd4d501461023d5780636750cd4c1461025d578063715018a61461027057600080fd5b806320efd722116100ee57806320efd7221461017f57806329460b0b1461019257806339e3f938146101a55780633c782a52146101c557600080fd5b806301ffc9a7146101205780630223536e146101485780630894edf11461015d5780631881d94d14610170575b600080fd5b61013361012e366004611cc0565b6102f9565b60405190151581526020015b60405180910390f35b61015b610156366004611d68565b610355565b005b61015b61016b366004611dc5565b610367565b600160405161013f9190611e11565b61015b61018d366004611ebb565b6104f9565b61015b6101a0366004611f0e565b61065a565b6101b86101b3366004611f64565b61083f565b60405161013f919061205b565b61020a6101d336600461206e565b600260209081526000938452604080852082529284528284209052825290205460ff811690610100900467ffffffffffffffff1682565b60408051921515835267ffffffffffffffff90911660208301520161013f565b6101b8610238366004611f64565b6109e0565b60408051600381526000602082015260029181019190915260600161013f565b61013361026b3660046120a3565b610d9a565b61015b610da5565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6102b36102ae3660046120be565b610db9565b60405161013f91906120f8565b61015b6102ce366004612165565b610e59565b6101336102e136600461238f565b610e69565b61015b6102f43660046123dd565b610e7e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f0ab7be9f00000000000000000000000000000000000000000000000000000000148061034f575061034f82610f35565b92915050565b61036184848484610fcc565b50505050565b61039283837f00000000000000000000000000000000000000000000000000000000000000006110e0565b600061039e84846111ae565b905060006103ac85856111c0565b905060006103ba83836109e0565b90506103de8187876040516103d09291906123f8565b6040518091039020866111e3565b600060405180606001604052808463ffffffff1681526020016104018989611392565b815260200161041089896113ab565b67ffffffffffffffff908116909152604080517fa825d747000000000000000000000000000000000000000000000000000000008152835163ffffffff1660048201526020840151602482015290830151909116604482015273ffffffffffffffffffffffffffffffffffffffff8681166064830152608482018890529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a825d7479060a401600060405180830381600087803b1580156104d857600080fd5b505af11580156104ec573d6000803e3d6000fd5b5050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610568576040517f467409c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610361573683838381811061058657610586612408565b90506020028101906105989190612437565b90506105af6105aa60208301836120a3565b6113ce565b60026105c160408301602084016120a3565b63ffffffff1603610601576105fc6105dc60208301836120a3565b866105ea6040850185612475565b8101906105f791906124da565b611415565b610651565b61061160408201602083016120a3565b6040517fba97c1fa00000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526024015b60405180910390fd5b5060010161056b565b61066261146b565b60005b81811015610801573683838381811061068057610680612408565b9050602002810190610692919061250f565b905060ff6106a36020830183612543565b6106b4906040810190602001612577565b60ff16036106ee576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff6106fd6020830183612543565b61070e906060810190604001612577565b60ff1603610748576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff61075e6020830183612543565b61076c906020810190612592565b67ffffffffffffffff16036107ad576040517f503667ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107cb6107bd6020830183612543565b6107c6906125ad565b6114ec565b6107f860006107dd60208401846120a3565b6107ea6020850185612543565b6107f3906125ad565b61153d565b50600101610665565b507faaf3aaa0c11056e86ac56eb653e25b005ca1a7d4dcd21ba24647f7ab63f3b5608282604051610833929190612669565b60405180910390a15050565b6040805160c0810182526000808252602082018190529181018290526060808201929092526080810182905260a081019190915273ffffffffffffffffffffffffffffffffffffffff8316600090815260016020818152604080842063ffffffff87168552825292839020835160c081018552815467ffffffffffffffff8116825260ff680100000000000000008204811683860152690100000000000000000082048116838801526a0100000000000000000000909104166060820152928101805485518185028101850190965280865293949193608086019383018282801561096057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610935575b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109cf57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a4575b505050505081525050905092915050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840181905260a084015263ffffffff85168083527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49825284832073ffffffffffffffffffffffffffffffffffffffff88168452600183528584209184529152929020805491929167ffffffffffffffff1680610a9057825467ffffffffffffffff168452610aaf565b67ffffffffffffffff81811614610aaf5767ffffffffffffffff811684525b815468010000000000000000900460ff16610b6557825468010000000000000000900460ff1615610b605782600101805480602002602001604051908101604052809291908181526020018280548015610b3f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610b14575b50505050506080850152825468010000000000000000900460ff1660208501525b610c03565b815468010000000000000000900460ff90811614610c035781600101805480602002602001604051908101604052809291908181526020018280548015610be257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610bb7575b50505050506080850152815468010000000000000000900460ff1660208501525b81546901000000000000000000900460ff16610cd25782546901000000000000000000900460ff1615610ccd5782600201805480602002602001604051908101604052809291908181526020018280548015610c9557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c6a575b505050505060a0850152825460ff69010000000000000000008204811660408701526a01000000000000000000009091041660608501525b610d88565b81546901000000000000000000900460ff90811614610d885781600201805480602002602001604051908101604052809291908181526020018280548015610d5057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d25575b505050505060a0850152815460ff69010000000000000000008204811660408701526a01000000000000000000009091041660608501525b610d91846114ec565b50505092915050565b600061034f826118d1565b610dad61146b565b610db76000611938565b565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe63ffffffff831601610e1857610df283856109e0565b604051602001610e02919061205b565b6040516020818303038152906040529050610e52565b6040517fba97c1fa00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610648565b9392505050565b610e648383836110e0565b505050565b6000610e768484846119ad565b949350505050565b610e8661146b565b73ffffffffffffffffffffffffffffffffffffffff8116610f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610648565b610f3281611938565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f97f0258400000000000000000000000000000000000000000000000000000000148061034f57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461034f565b6040805180820182526001815267ffffffffffffffff831660208201529051600290600090610ffe90889088906123f8565b6040805191829003909120825260208083019390935290810160009081208682528352818120338083529084529082902084518154959094015167ffffffffffffffff16610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff941515949094167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909516949094179290921790925590517f2cb0eed7538baeae4c6fde038c0fd0384d27de0dd55a228c65847bda6aa1ab56916110d2918790879086908890612806565b60405180910390a150505050565b6051821461111a576040517fc9bf37b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016111268484611ab6565b60ff1614611160576040517f3a9ae7b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8063ffffffff166111718484611ad8565b63ffffffff1614610e64576040517f42d2c97e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e526111bd8484611ae8565b90565b60006111d0600d6009848661288b565b6111d9916128b5565b60e01c9392505050565b6111ee8383836119ad565b611224576040517f4c3118d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160ff16156112dc5760005b836020015160ff168160ff1610156112da57600083815260026020908152604080832085845290915281206080860151805191929160ff851690811061127c5761127c612408565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000169055600101611234565b505b604083015160ff1615610e645760005b836040015160ff168160ff161015610361576000838152600260209081526040808320858452909152812060a0860151805191929160ff851690811061133457611334612408565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001690556001016112ec565b60006113a2602d600d848661288b565b610e52916128fd565b60006113bb60096001848661288b565b6113c491612939565b60c01c9392505050565b6113d7816118d1565b610f32576040517ff0c10d0400000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610648565b61142082848361153d565b61142a82846109e0565b507f82118522aa536ac0e96cc5c689407ae42b89d592aa133890a01f1509842f508182848360405161145e9392919061297f565b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610648565b602081015160ff161580156115065750606081015160ff16155b15610f32576040517fce2c375100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160ff90811614806115585750602081015160ff16155b1561159f576080810151511561159a576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161e565b806020015160ff168160800151511415806115da575060026115c3600160ff6129e9565b6115cd9190612a02565b60ff16816020015160ff16115b15611611576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161e8160800151611af8565b604081015160ff90811614806116395750604081015160ff16155b156116bf5760a0810151511561167b576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081015160ff16156116ba576040517f38682fa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611796565b806040015160ff168160a00151511415806116fa575060026116e3600160ff6129e9565b6116ed9190612a02565b60ff16816040015160ff16115b15611731576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081015160ff1615806117525750806040015160ff16816060015160ff16115b15611789576040517f38682fa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117968160a00151611af8565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020818152604080842063ffffffff87168552825292839020845181548684015195870151606088015167ffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909216919091176801000000000000000060ff97881602177fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff166901000000000000000000918716919091027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff16176a01000000000000000000009590911694909402939093178355608084015180518594936118ad93908501920190611c21565b5060a082015180516118c9916002840191602090910190611c21565b505050505050565b63ffffffff811660009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4960205260408120805468010000000000000000900460ff16151580610e525750546a0100000000000000000000900460ff16151592915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b602083015160009060ff1615611a305760005b846020015160ff168160ff161015611a1857611a0285608001518260ff16815181106119ee576119ee612408565b602002602001015185858860000151611b92565b611a10576000915050610e52565b6001016119c0565b50836040015160ff16600003611a3057506001610e52565b606084015160005b856040015160ff168160ff161015611aaa57611a7a8660a001518260ff1681518110611a6657611a66612408565b602002602001015186868960000151611b92565b15611aa25781611a8981612a4b565b9250508160ff16600003611aa257600192505050610e52565b600101611a38565b50600095945050505050565b6000611ac5600182848661288b565b611ace91612a86565b60f81c9392505050565b60006111d06031602d848661288b565b60006113a260516031848661288b565b6000805b8251811015610e64576000838281518110611b1957611b19612408565b602002602001015190508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1611611b88576040517f447516e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9150600101611afc565b6000838152600260209081526040808320858452825280832073ffffffffffffffffffffffffffffffffffffffff88168452825280832081518083019092525460ff811615801580845261010090920467ffffffffffffffff16938301939093529091611c1757508267ffffffffffffffff16816020015167ffffffffffffffff1610155b9695505050505050565b828054828255906000526020600020908101928215611c9b579160200282015b82811115611c9b57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611c41565b50611ca7929150611cab565b5090565b5b80821115611ca75760008155600101611cac565b600060208284031215611cd257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e5257600080fd5b60008083601f840112611d1457600080fd5b50813567ffffffffffffffff811115611d2c57600080fd5b602083019150836020828501011115611d4457600080fd5b9250929050565b803567ffffffffffffffff81168114611d6357600080fd5b919050565b60008060008060608587031215611d7e57600080fd5b843567ffffffffffffffff811115611d9557600080fd5b611da187828801611d02565b90955093505060208501359150611dba60408601611d4b565b905092959194509250565b600080600060408486031215611dda57600080fd5b833567ffffffffffffffff811115611df157600080fd5b611dfd86828701611d02565b909790965060209590950135949350505050565b6020810160038310611e4c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d6357600080fd5b60008083601f840112611e8857600080fd5b50813567ffffffffffffffff811115611ea057600080fd5b6020830191508360208260051b8501011115611d4457600080fd5b600080600060408486031215611ed057600080fd5b611ed984611e52565b9250602084013567ffffffffffffffff811115611ef557600080fd5b611f0186828701611e76565b9497909650939450505050565b60008060208385031215611f2157600080fd5b823567ffffffffffffffff811115611f3857600080fd5b611f4485828601611e76565b90969095509350505050565b803563ffffffff81168114611d6357600080fd5b60008060408385031215611f7757600080fd5b611f8083611e52565b9150611f8e60208401611f50565b90509250929050565b60008151808452602080850194506020840160005b83811015611fde57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611fac565b509495945050505050565b67ffffffffffffffff815116825260ff602082015116602083015260ff604082015116604083015260ff60608201511660608301526000608082015160c0608085015261203960c0850182611f97565b905060a083015184820360a08601526120528282611f97565b95945050505050565b602081526000610e526020830184611fe9565b60008060006060848603121561208357600080fd5b833592506020840135915061209a60408501611e52565b90509250925092565b6000602082840312156120b557600080fd5b610e5282611f50565b6000806000606084860312156120d357600080fd5b6120dc84611f50565b92506120ea60208501611e52565b915061209a60408501611f50565b60006020808352835180602085015260005b818110156121265785810183015185820160400152820161210a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008060006040848603121561217a57600080fd5b833567ffffffffffffffff81111561219157600080fd5b61219d86828701611d02565b909450925061209a905060208501611f50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715612202576122026121b0565b60405290565b803560ff81168114611d6357600080fd5b600082601f83011261222a57600080fd5b8135602067ffffffffffffffff80831115612247576122476121b0565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561228a5761228a6121b0565b60405293845260208187018101949081019250878511156122aa57600080fd5b6020870191505b848210156122d1576122c282611e52565b835291830191908301906122b1565b979650505050505050565b600060c082840312156122ee57600080fd5b6122f66121df565b905061230182611d4b565b815261230f60208301612208565b602082015261232060408301612208565b604082015261233160608301612208565b6060820152608082013567ffffffffffffffff8082111561235157600080fd5b61235d85838601612219565b608084015260a084013591508082111561237657600080fd5b5061238384828501612219565b60a08301525092915050565b6000806000606084860312156123a457600080fd5b833567ffffffffffffffff8111156123bb57600080fd5b6123c7868287016122dc565b9660208601359650604090950135949350505050565b6000602082840312156123ef57600080fd5b610e5282611e52565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261246b57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126124aa57600080fd5b83018035915067ffffffffffffffff8211156124c557600080fd5b602001915036819003821315611d4457600080fd5b6000602082840312156124ec57600080fd5b813567ffffffffffffffff81111561250357600080fd5b610e76848285016122dc565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261246b57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261246b57600080fd5b60006020828403121561258957600080fd5b610e5282612208565b6000602082840312156125a457600080fd5b610e5282611d4b565b600061034f36836122dc565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126125ee57600080fd5b830160208101925035905067ffffffffffffffff81111561260e57600080fd5b8060051b3603821315611d4457600080fd5b8183526000602080850194508260005b85811015611fde5773ffffffffffffffffffffffffffffffffffffffff61265683611e52565b1687529582019590820190600101612630565b60208082528181018390526000906040808401600586901b8501820187855b888110156127f8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08089850301855282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18c36030181126126ea57600080fd5b8b0163ffffffff6126fa82611f50565b168552878101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4182360301811261273157600080fd5b8589018890520167ffffffffffffffff61274a82611d4b565b168786015261275a888201612208565b606060ff808316828901526127708a8501612208565b92506080818416818a0152612786838601612208565b935060a09250818416838a015261279f818601866125b9565b60c08b810152945091506127ba905061010089018483612620565b9250506127c9818401846125b9565b93509050838783030160e08801526127e2828483612620565b978a019796505050928701925050600101612688565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8616815260806020820152836080820152838560a0830137600060a08583010152600060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f870116830101905067ffffffffffffffff841660408301528260608301529695505050505050565b6000808585111561289b57600080fd5b838611156128a857600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156128f55780818660040360031b1b83161692505b505092915050565b8035602083101561034f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffff00000000000000000000000000000000000000000000000081358181169160088510156128f55760089490940360031b84901b1690921692915050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff831660208201526060604082015260006120526060830184611fe9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561034f5761034f6129ba565b600060ff831680612a3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b600060ff821680612a5e57612a5e6129ba565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7fff0000000000000000000000000000000000000000000000000000000000000081358181169160018510156128f55760019490940360031b84901b169092169291505056fea264697066735822122089779ddf355286c32eeb3fc47b72cbbd5c19a6abb67086e252341f8d077313bc64736f6c634300081600330000000000000000000000001a44076050125825900e736c501f859c50fe728c
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806343ea4fa9116100b25780638da5cb5b11610081578063c40ff83511610066578063c40ff835146102c0578063e084d952146102d3578063f2fde38b146102e657600080fd5b80638da5cb5b146102785780639c33abf7146102a057600080fd5b806343ea4fa91461022a57806354fd4d501461023d5780636750cd4c1461025d578063715018a61461027057600080fd5b806320efd722116100ee57806320efd7221461017f57806329460b0b1461019257806339e3f938146101a55780633c782a52146101c557600080fd5b806301ffc9a7146101205780630223536e146101485780630894edf11461015d5780631881d94d14610170575b600080fd5b61013361012e366004611cc0565b6102f9565b60405190151581526020015b60405180910390f35b61015b610156366004611d68565b610355565b005b61015b61016b366004611dc5565b610367565b600160405161013f9190611e11565b61015b61018d366004611ebb565b6104f9565b61015b6101a0366004611f0e565b61065a565b6101b86101b3366004611f64565b61083f565b60405161013f919061205b565b61020a6101d336600461206e565b600260209081526000938452604080852082529284528284209052825290205460ff811690610100900467ffffffffffffffff1682565b60408051921515835267ffffffffffffffff90911660208301520161013f565b6101b8610238366004611f64565b6109e0565b60408051600381526000602082015260029181019190915260600161013f565b61013361026b3660046120a3565b610d9a565b61015b610da5565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013f565b6102b36102ae3660046120be565b610db9565b60405161013f91906120f8565b61015b6102ce366004612165565b610e59565b6101336102e136600461238f565b610e69565b61015b6102f43660046123dd565b610e7e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f0ab7be9f00000000000000000000000000000000000000000000000000000000148061034f575061034f82610f35565b92915050565b61036184848484610fcc565b50505050565b61039283837f00000000000000000000000000000000000000000000000000000000000075df6110e0565b600061039e84846111ae565b905060006103ac85856111c0565b905060006103ba83836109e0565b90506103de8187876040516103d09291906123f8565b6040518091039020866111e3565b600060405180606001604052808463ffffffff1681526020016104018989611392565b815260200161041089896113ab565b67ffffffffffffffff908116909152604080517fa825d747000000000000000000000000000000000000000000000000000000008152835163ffffffff1660048201526020840151602482015290830151909116604482015273ffffffffffffffffffffffffffffffffffffffff8681166064830152608482018890529192507f0000000000000000000000001a44076050125825900e736c501f859c50fe728c9091169063a825d7479060a401600060405180830381600087803b1580156104d857600080fd5b505af11580156104ec573d6000803e3d6000fd5b5050505050505050505050565b7f0000000000000000000000001a44076050125825900e736c501f859c50fe728c73ffffffffffffffffffffffffffffffffffffffff163314610568576040517f467409c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610361573683838381811061058657610586612408565b90506020028101906105989190612437565b90506105af6105aa60208301836120a3565b6113ce565b60026105c160408301602084016120a3565b63ffffffff1603610601576105fc6105dc60208301836120a3565b866105ea6040850185612475565b8101906105f791906124da565b611415565b610651565b61061160408201602083016120a3565b6040517fba97c1fa00000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526024015b60405180910390fd5b5060010161056b565b61066261146b565b60005b81811015610801573683838381811061068057610680612408565b9050602002810190610692919061250f565b905060ff6106a36020830183612543565b6106b4906040810190602001612577565b60ff16036106ee576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff6106fd6020830183612543565b61070e906060810190604001612577565b60ff1603610748576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff61075e6020830183612543565b61076c906020810190612592565b67ffffffffffffffff16036107ad576040517f503667ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107cb6107bd6020830183612543565b6107c6906125ad565b6114ec565b6107f860006107dd60208401846120a3565b6107ea6020850185612543565b6107f3906125ad565b61153d565b50600101610665565b507faaf3aaa0c11056e86ac56eb653e25b005ca1a7d4dcd21ba24647f7ab63f3b5608282604051610833929190612669565b60405180910390a15050565b6040805160c0810182526000808252602082018190529181018290526060808201929092526080810182905260a081019190915273ffffffffffffffffffffffffffffffffffffffff8316600090815260016020818152604080842063ffffffff87168552825292839020835160c081018552815467ffffffffffffffff8116825260ff680100000000000000008204811683860152690100000000000000000082048116838801526a0100000000000000000000909104166060820152928101805485518185028101850190965280865293949193608086019383018282801561096057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610935575b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109cf57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a4575b505050505081525050905092915050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840181905260a084015263ffffffff85168083527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49825284832073ffffffffffffffffffffffffffffffffffffffff88168452600183528584209184529152929020805491929167ffffffffffffffff1680610a9057825467ffffffffffffffff168452610aaf565b67ffffffffffffffff81811614610aaf5767ffffffffffffffff811684525b815468010000000000000000900460ff16610b6557825468010000000000000000900460ff1615610b605782600101805480602002602001604051908101604052809291908181526020018280548015610b3f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610b14575b50505050506080850152825468010000000000000000900460ff1660208501525b610c03565b815468010000000000000000900460ff90811614610c035781600101805480602002602001604051908101604052809291908181526020018280548015610be257602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610bb7575b50505050506080850152815468010000000000000000900460ff1660208501525b81546901000000000000000000900460ff16610cd25782546901000000000000000000900460ff1615610ccd5782600201805480602002602001604051908101604052809291908181526020018280548015610c9557602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c6a575b505050505060a0850152825460ff69010000000000000000008204811660408701526a01000000000000000000009091041660608501525b610d88565b81546901000000000000000000900460ff90811614610d885781600201805480602002602001604051908101604052809291908181526020018280548015610d5057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d25575b505050505060a0850152815460ff69010000000000000000008204811660408701526a01000000000000000000009091041660608501525b610d91846114ec565b50505092915050565b600061034f826118d1565b610dad61146b565b610db76000611938565b565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe63ffffffff831601610e1857610df283856109e0565b604051602001610e02919061205b565b6040516020818303038152906040529050610e52565b6040517fba97c1fa00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610648565b9392505050565b610e648383836110e0565b505050565b6000610e768484846119ad565b949350505050565b610e8661146b565b73ffffffffffffffffffffffffffffffffffffffff8116610f29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610648565b610f3281611938565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f97f0258400000000000000000000000000000000000000000000000000000000148061034f57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461034f565b6040805180820182526001815267ffffffffffffffff831660208201529051600290600090610ffe90889088906123f8565b6040805191829003909120825260208083019390935290810160009081208682528352818120338083529084529082902084518154959094015167ffffffffffffffff16610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff941515949094167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909516949094179290921790925590517f2cb0eed7538baeae4c6fde038c0fd0384d27de0dd55a228c65847bda6aa1ab56916110d2918790879086908890612806565b60405180910390a150505050565b6051821461111a576040517fc9bf37b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016111268484611ab6565b60ff1614611160576040517f3a9ae7b900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8063ffffffff166111718484611ad8565b63ffffffff1614610e64576040517f42d2c97e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e526111bd8484611ae8565b90565b60006111d0600d6009848661288b565b6111d9916128b5565b60e01c9392505050565b6111ee8383836119ad565b611224576040517f4c3118d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160ff16156112dc5760005b836020015160ff168160ff1610156112da57600083815260026020908152604080832085845290915281206080860151805191929160ff851690811061127c5761127c612408565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000169055600101611234565b505b604083015160ff1615610e645760005b836040015160ff168160ff161015610361576000838152600260209081526040808320858452909152812060a0860151805191929160ff851690811061133457611334612408565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001690556001016112ec565b60006113a2602d600d848661288b565b610e52916128fd565b60006113bb60096001848661288b565b6113c491612939565b60c01c9392505050565b6113d7816118d1565b610f32576040517ff0c10d0400000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610648565b61142082848361153d565b61142a82846109e0565b507f82118522aa536ac0e96cc5c689407ae42b89d592aa133890a01f1509842f508182848360405161145e9392919061297f565b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610648565b602081015160ff161580156115065750606081015160ff16155b15610f32576040517fce2c375100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160ff90811614806115585750602081015160ff16155b1561159f576080810151511561159a576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161e565b806020015160ff168160800151511415806115da575060026115c3600160ff6129e9565b6115cd9190612a02565b60ff16816020015160ff16115b15611611576040517f83aa17da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61161e8160800151611af8565b604081015160ff90811614806116395750604081015160ff16155b156116bf5760a0810151511561167b576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081015160ff16156116ba576040517f38682fa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611796565b806040015160ff168160a00151511415806116fa575060026116e3600160ff6129e9565b6116ed9190612a02565b60ff16816040015160ff16115b15611731576040517f4221136600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606081015160ff1615806117525750806040015160ff16816060015160ff16115b15611789576040517f38682fa900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117968160a00151611af8565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020818152604080842063ffffffff87168552825292839020845181548684015195870151606088015167ffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909216919091176801000000000000000060ff97881602177fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff166901000000000000000000918716919091027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff16176a01000000000000000000009590911694909402939093178355608084015180518594936118ad93908501920190611c21565b5060a082015180516118c9916002840191602090910190611c21565b505050505050565b63ffffffff811660009081527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4960205260408120805468010000000000000000900460ff16151580610e525750546a0100000000000000000000900460ff16151592915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b602083015160009060ff1615611a305760005b846020015160ff168160ff161015611a1857611a0285608001518260ff16815181106119ee576119ee612408565b602002602001015185858860000151611b92565b611a10576000915050610e52565b6001016119c0565b50836040015160ff16600003611a3057506001610e52565b606084015160005b856040015160ff168160ff161015611aaa57611a7a8660a001518260ff1681518110611a6657611a66612408565b602002602001015186868960000151611b92565b15611aa25781611a8981612a4b565b9250508160ff16600003611aa257600192505050610e52565b600101611a38565b50600095945050505050565b6000611ac5600182848661288b565b611ace91612a86565b60f81c9392505050565b60006111d06031602d848661288b565b60006113a260516031848661288b565b6000805b8251811015610e64576000838281518110611b1957611b19612408565b602002602001015190508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1611611b88576040517f447516e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9150600101611afc565b6000838152600260209081526040808320858452825280832073ffffffffffffffffffffffffffffffffffffffff88168452825280832081518083019092525460ff811615801580845261010090920467ffffffffffffffff16938301939093529091611c1757508267ffffffffffffffff16816020015167ffffffffffffffff1610155b9695505050505050565b828054828255906000526020600020908101928215611c9b579160200282015b82811115611c9b57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611c41565b50611ca7929150611cab565b5090565b5b80821115611ca75760008155600101611cac565b600060208284031215611cd257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e5257600080fd5b60008083601f840112611d1457600080fd5b50813567ffffffffffffffff811115611d2c57600080fd5b602083019150836020828501011115611d4457600080fd5b9250929050565b803567ffffffffffffffff81168114611d6357600080fd5b919050565b60008060008060608587031215611d7e57600080fd5b843567ffffffffffffffff811115611d9557600080fd5b611da187828801611d02565b90955093505060208501359150611dba60408601611d4b565b905092959194509250565b600080600060408486031215611dda57600080fd5b833567ffffffffffffffff811115611df157600080fd5b611dfd86828701611d02565b909790965060209590950135949350505050565b6020810160038310611e4c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d6357600080fd5b60008083601f840112611e8857600080fd5b50813567ffffffffffffffff811115611ea057600080fd5b6020830191508360208260051b8501011115611d4457600080fd5b600080600060408486031215611ed057600080fd5b611ed984611e52565b9250602084013567ffffffffffffffff811115611ef557600080fd5b611f0186828701611e76565b9497909650939450505050565b60008060208385031215611f2157600080fd5b823567ffffffffffffffff811115611f3857600080fd5b611f4485828601611e76565b90969095509350505050565b803563ffffffff81168114611d6357600080fd5b60008060408385031215611f7757600080fd5b611f8083611e52565b9150611f8e60208401611f50565b90509250929050565b60008151808452602080850194506020840160005b83811015611fde57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611fac565b509495945050505050565b67ffffffffffffffff815116825260ff602082015116602083015260ff604082015116604083015260ff60608201511660608301526000608082015160c0608085015261203960c0850182611f97565b905060a083015184820360a08601526120528282611f97565b95945050505050565b602081526000610e526020830184611fe9565b60008060006060848603121561208357600080fd5b833592506020840135915061209a60408501611e52565b90509250925092565b6000602082840312156120b557600080fd5b610e5282611f50565b6000806000606084860312156120d357600080fd5b6120dc84611f50565b92506120ea60208501611e52565b915061209a60408501611f50565b60006020808352835180602085015260005b818110156121265785810183015185820160400152820161210a565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008060006040848603121561217a57600080fd5b833567ffffffffffffffff81111561219157600080fd5b61219d86828701611d02565b909450925061209a905060208501611f50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715612202576122026121b0565b60405290565b803560ff81168114611d6357600080fd5b600082601f83011261222a57600080fd5b8135602067ffffffffffffffff80831115612247576122476121b0565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561228a5761228a6121b0565b60405293845260208187018101949081019250878511156122aa57600080fd5b6020870191505b848210156122d1576122c282611e52565b835291830191908301906122b1565b979650505050505050565b600060c082840312156122ee57600080fd5b6122f66121df565b905061230182611d4b565b815261230f60208301612208565b602082015261232060408301612208565b604082015261233160608301612208565b6060820152608082013567ffffffffffffffff8082111561235157600080fd5b61235d85838601612219565b608084015260a084013591508082111561237657600080fd5b5061238384828501612219565b60a08301525092915050565b6000806000606084860312156123a457600080fd5b833567ffffffffffffffff8111156123bb57600080fd5b6123c7868287016122dc565b9660208601359650604090950135949350505050565b6000602082840312156123ef57600080fd5b610e5282611e52565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261246b57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126124aa57600080fd5b83018035915067ffffffffffffffff8211156124c557600080fd5b602001915036819003821315611d4457600080fd5b6000602082840312156124ec57600080fd5b813567ffffffffffffffff81111561250357600080fd5b610e76848285016122dc565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261246b57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261246b57600080fd5b60006020828403121561258957600080fd5b610e5282612208565b6000602082840312156125a457600080fd5b610e5282611d4b565b600061034f36836122dc565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126125ee57600080fd5b830160208101925035905067ffffffffffffffff81111561260e57600080fd5b8060051b3603821315611d4457600080fd5b8183526000602080850194508260005b85811015611fde5773ffffffffffffffffffffffffffffffffffffffff61265683611e52565b1687529582019590820190600101612630565b60208082528181018390526000906040808401600586901b8501820187855b888110156127f8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08089850301855282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18c36030181126126ea57600080fd5b8b0163ffffffff6126fa82611f50565b168552878101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4182360301811261273157600080fd5b8589018890520167ffffffffffffffff61274a82611d4b565b168786015261275a888201612208565b606060ff808316828901526127708a8501612208565b92506080818416818a0152612786838601612208565b935060a09250818416838a015261279f818601866125b9565b60c08b810152945091506127ba905061010089018483612620565b9250506127c9818401846125b9565b93509050838783030160e08801526127e2828483612620565b978a019796505050928701925050600101612688565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8616815260806020820152836080820152838560a0830137600060a08583010152600060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f870116830101905067ffffffffffffffff841660408301528260608301529695505050505050565b6000808585111561289b57600080fd5b838611156128a857600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156128f55780818660040360031b1b83161692505b505092915050565b8035602083101561034f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7fffffffffffffffff00000000000000000000000000000000000000000000000081358181169160088510156128f55760089490940360031b84901b1690921692915050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff831660208201526060604082015260006120526060830184611fe9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561034f5761034f6129ba565b600060ff831680612a3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b600060ff821680612a5e57612a5e6129ba565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0192915050565b7fff0000000000000000000000000000000000000000000000000000000000000081358181169160018510156128f55760019490940360031b84901b169092169291505056fea264697066735822122089779ddf355286c32eeb3fc47b72cbbd5c19a6abb67086e252341f8d077313bc64736f6c63430008160033