Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
GGUSDOFT
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import {OFTFeeUpgradeable} from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTFeeUpgradeable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; contract GGUSDOFT is OFTFeeUpgradeable { address private feeAddress; mapping(address => bool) private whitelist; uint256 private nonce; event FeeAddress(address feeAddress); event WhitelistUpdated(address indexed account, bool isWhitelisted); event TransferEx(address indexed from, address indexed to, uint256 indexed nonce, uint256 value, uint256 fromBalanceAfterTransfer, uint256 toBalanceAfterTransfer); constructor(address _lzEndpoint) OFTFeeUpgradeable(_lzEndpoint) { _disableInitializers(); } function initialize( string memory _name, string memory _symbol, address _delegate ) public initializer { __OFT_init(_name, _symbol, _delegate); __Ownable_init(_delegate); feeAddress = address(0); } function setFeeAddress(address _feeAddress) external onlyOwner { feeAddress = _feeAddress; emit FeeAddress(feeAddress); } function getFeeAddress() public view virtual returns (address) { return feeAddress; } function addToWhitelist(address _account) external onlyOwner { require(!whitelist[_account], "Already whitelisted"); whitelist[_account] = true; emit WhitelistUpdated(_account, true); } function removeFromWhitelist(address _account) external onlyOwner { require(whitelist[_account], "Not whitelisted"); whitelist[_account] = false; emit WhitelistUpdated(_account, false); } function isWhitelisted(address _account) public view returns (bool) { return whitelist[_account]; } function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal override virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = whitelist[_from] ? _debitViewNoFee(_amountLD, _minAmountLD) : _debitView(_amountLD, _minAmountLD, _dstEid); if (amountReceivedLD > amountSentLD) { revert("Amount received cannot be greater than amount sent"); } uint256 fee = amountSentLD - amountReceivedLD; if (fee > 0) { if (feeAddress == address(0)) { OFTFeeStorage storage $ = _getOFTFeeStorage(); unchecked { $.feeBalance += fee; } _transfer(_from, address(this), fee); } else { // transfer fee to special account _transfer(_from, feeAddress, fee); } } _burn(_from, amountReceivedLD); } function _debitViewNoFee( uint256 _amountLD, uint256 _minAmountLD ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; unchecked { amountReceivedLD = _removeDust(_amountLD); } if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } function decimals() public override view virtual returns (uint8){ return 6; } function _update(address from, address to, uint256 value) internal override virtual { super._update(from, to, value); nonce++; emit TransferEx(from, to, nonce, value, balanceOf(from), balanceOf(to)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { IMessageLibManager } from "./IMessageLibManager.sol"; import { IMessagingComposer } from "./IMessagingComposer.sol"; import { IMessagingChannel } from "./IMessagingChannel.sol"; import { IMessagingContext } from "./IMessagingContext.sol"; struct MessagingParams { uint32 dstEid; bytes32 receiver; bytes message; bytes options; bool payInLzToken; } struct MessagingReceipt { bytes32 guid; uint64 nonce; MessagingFee fee; } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } struct Origin { uint32 srcEid; bytes32 sender; uint64 nonce; } interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext { event PacketSent(bytes encodedPayload, bytes options, address sendLibrary); event PacketVerified(Origin origin, address receiver, bytes32 payloadHash); event PacketDelivered(Origin origin, address receiver); event LzReceiveAlert( address indexed receiver, address indexed executor, Origin origin, bytes32 guid, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); event LzTokenSet(address token); event DelegateSet(address sender, address delegate); function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory); function send( MessagingParams calldata _params, address _refundAddress ) external payable returns (MessagingReceipt memory); function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external; function verifiable(Origin calldata _origin, address _receiver) external view returns (bool); function initializable(Origin calldata _origin, address _receiver) external view returns (bool); function lzReceive( Origin calldata _origin, address _receiver, bytes32 _guid, bytes calldata _message, bytes calldata _extraData ) external payable; // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external; function setLzToken(address _lzToken) external; function lzToken() external view returns (address); function nativeToken() external view returns (address); function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { Origin } from "./ILayerZeroEndpointV2.sol"; interface ILayerZeroReceiver { function allowInitializePath(Origin calldata _origin) external view returns (bool); function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64); function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { SetConfigParam } from "./IMessageLibManager.sol"; enum MessageLibType { Send, Receive, SendAndReceive } interface IMessageLib is IERC165 { function setConfig(address _oapp, SetConfigParam[] calldata _config) external; function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config); function isSupportedEid(uint32 _eid) external view returns (bool); // message libs of same major version are compatible function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion); function messageLibType() external view returns (MessageLibType); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; struct SetConfigParam { uint32 eid; uint32 configType; bytes config; } interface IMessageLibManager { struct Timeout { address lib; uint256 expiry; } event LibraryRegistered(address newLib); event DefaultSendLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry); event SendLibrarySet(address sender, uint32 eid, address newLib); event ReceiveLibrarySet(address receiver, uint32 eid, address newLib); event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout); function registerLibrary(address _lib) external; function isRegisteredLibrary(address _lib) external view returns (bool); function getRegisteredLibraries() external view returns (address[] memory); function setDefaultSendLibrary(uint32 _eid, address _newLib) external; function defaultSendLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingChannel { event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce); event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); function eid() external view returns (uint32); // this is an emergency function if a message cannot be verified for some reasons // required to provide _nextNonce to avoid race condition function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external; function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32); function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64); function inboundPayloadHash( address _receiver, uint32 _srcEid, bytes32 _sender, uint64 _nonce ) external view returns (bytes32); function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingComposer { event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message); event ComposeDelivered(address from, address to, bytes32 guid, uint16 index); event LzComposeAlert( address indexed from, address indexed to, address indexed executor, bytes32 guid, uint16 index, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); function composeQueue( address _from, address _to, bytes32 _guid, uint16 _index ) external view returns (bytes32 messageHash); function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external; function lzCompose( address _from, address _to, bytes32 _guid, uint16 _index, bytes calldata _message, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingContext { function isSendingMessage() external view returns (bool); function getSendContext() external view returns (uint32 dstEid, address sender); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { MessagingFee } from "./ILayerZeroEndpointV2.sol"; import { IMessageLib } from "./IMessageLib.sol"; struct Packet { uint64 nonce; uint32 srcEid; address sender; uint32 dstEid; bytes32 receiver; bytes32 guid; bytes message; } interface ISendLib is IMessageLib { function send( Packet calldata _packet, bytes calldata _options, bool _payInLzToken ) external returns (MessagingFee memory, bytes memory encodedPacket); function quote( Packet calldata _packet, bytes calldata _options, bool _payInLzToken ) external view returns (MessagingFee memory); function setTreasury(address _treasury) external; function withdrawFee(address _to, uint256 _amount) external; function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external; }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; library AddressCast { error AddressCast_InvalidSizeForAddress(); error AddressCast_InvalidAddress(); function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) { if (_addressBytes.length > 32) revert AddressCast_InvalidAddress(); result = bytes32(_addressBytes); unchecked { uint256 offset = 32 - _addressBytes.length; result = result >> (offset * 8); } } function toBytes32(address _address) internal pure returns (bytes32 result) { result = bytes32(uint256(uint160(_address))); } function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) { if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress(); result = new bytes(_size); unchecked { uint256 offset = 256 - _size * 8; assembly { mstore(add(result, 32), shl(offset, _addressBytes32)) } } } function toAddress(bytes32 _addressBytes32) internal pure returns (address result) { result = address(uint160(uint256(_addressBytes32))); } function toAddress(bytes calldata _addressBytes) internal pure returns (address result) { if (_addressBytes.length != 20) revert AddressCast_InvalidAddress(); result = address(bytes20(_addressBytes)); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { Packet } from "../../interfaces/ISendLib.sol"; import { AddressCast } from "../../libs/AddressCast.sol"; library PacketV1Codec { using AddressCast for address; using AddressCast for bytes32; uint8 internal constant PACKET_VERSION = 1; // header (version + nonce + path) // version uint256 private constant PACKET_VERSION_OFFSET = 0; // nonce uint256 private constant NONCE_OFFSET = 1; // path uint256 private constant SRC_EID_OFFSET = 9; uint256 private constant SENDER_OFFSET = 13; uint256 private constant DST_EID_OFFSET = 45; uint256 private constant RECEIVER_OFFSET = 49; // payload (guid + message) uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path) uint256 private constant MESSAGE_OFFSET = 113; function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) { encodedPacket = abi.encodePacked( PACKET_VERSION, _packet.nonce, _packet.srcEid, _packet.sender.toBytes32(), _packet.dstEid, _packet.receiver, _packet.guid, _packet.message ); } function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) { return abi.encodePacked( PACKET_VERSION, _packet.nonce, _packet.srcEid, _packet.sender.toBytes32(), _packet.dstEid, _packet.receiver ); } function encodePayload(Packet memory _packet) internal pure returns (bytes memory) { return abi.encodePacked(_packet.guid, _packet.message); } function header(bytes calldata _packet) internal pure returns (bytes calldata) { return _packet[0:GUID_OFFSET]; } function version(bytes calldata _packet) internal pure returns (uint8) { return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET])); } function nonce(bytes calldata _packet) internal pure returns (uint64) { return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET])); } function srcEid(bytes calldata _packet) internal pure returns (uint32) { return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET])); } function sender(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]); } function senderAddressB20(bytes calldata _packet) internal pure returns (address) { return sender(_packet).toAddress(); } function dstEid(bytes calldata _packet) internal pure returns (uint32) { return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET])); } function receiver(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]); } function receiverB20(bytes calldata _packet) internal pure returns (address) { return receiver(_packet).toAddress(); } function guid(bytes calldata _packet) internal pure returns (bytes32) { return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]); } function message(bytes calldata _packet) internal pure returns (bytes calldata) { return bytes(_packet[MESSAGE_OFFSET:]); } function payload(bytes calldata _packet) internal pure returns (bytes calldata) { return bytes(_packet[GUID_OFFSET:]); } function payloadHash(bytes calldata _packet) internal pure returns (bytes32) { return keccak256(payload(_packet)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { IOAppOptionsType3, EnforcedOptionParam } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol"; /** * @title OAppOptionsType3 * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options. */ abstract contract OAppOptionsType3Upgradeable is IOAppOptionsType3, OwnableUpgradeable { struct OAppOptionsType3Storage { // @dev The "msgType" should be defined in the child contract. mapping(uint32 => mapping(uint16 => bytes)) enforcedOptions; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappoptionstype3")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION = 0x8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea0000; uint16 internal constant OPTION_TYPE_3 = 3; function _getOAppOptionsType3Storage() internal pure returns (OAppOptionsType3Storage storage $) { assembly { $.slot := OAPP_OPTIONS_TYPE_3_STORAGE_LOCATION } } /** * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OAppOptionsType3_init() internal onlyInitializing {} function __OAppOptionsType3_init_unchained() internal onlyInitializing {} function enforcedOptions(uint32 _eid, uint16 _msgType) public view returns (bytes memory) { OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage(); return $.enforcedOptions[_eid][_msgType]; } /** * @dev Sets the enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc. * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType. * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose(). */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner { OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage(); for (uint256 i = 0; i < _enforcedOptions.length; i++) { // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining. _assertOptionsType3(_enforcedOptions[i].options); $.enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options; } emit EnforcedOptionSet(_enforcedOptions); } /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OAPP message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. * * @dev If there is an enforced lzReceive option: * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether} * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function. * @dev This presence of duplicated options is handled off-chain in the verifier/executor. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) public view virtual returns (bytes memory) { OAppOptionsType3Storage storage $ = _getOAppOptionsType3Storage(); bytes memory enforced = $.enforcedOptions[_eid][_msgType]; // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options. if (enforced.length == 0) return _extraOptions; // No caller options, return enforced if (_extraOptions.length == 0) return enforced; // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined. if (_extraOptions.length >= 2) { _assertOptionsType3(_extraOptions); // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced. return bytes.concat(enforced, _extraOptions[2:]); } // No valid set of options was found. revert InvalidOptions(_extraOptions); } /** * @dev Internal function to assert that options are of type 3. * @param _options The options to be checked. */ function _assertOptionsType3(bytes calldata _options) internal pure virtual { uint16 optionsType = uint16(bytes2(_options[0:2])); if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { IOAppCore, ILayerZeroEndpointV2 } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; /** * @title OAppCore * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations. */ abstract contract OAppCoreUpgradeable is IOAppCore, OwnableUpgradeable { struct OAppCoreStorage { mapping(uint32 => bytes32) peers; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappcore")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OAPP_CORE_STORAGE_LOCATION = 0x72ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900; function _getOAppCoreStorage() internal pure returns (OAppCoreStorage storage $) { assembly { $.slot := OAPP_CORE_STORAGE_LOCATION } } // The LayerZero endpoint associated with the given OApp ILayerZeroEndpointV2 public immutable endpoint; /** * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate. * @param _endpoint The address of the LOCAL Layer Zero endpoint. */ constructor(address _endpoint) { endpoint = ILayerZeroEndpointV2(_endpoint); } /** * @dev Initializes the OAppCore with the provided delegate. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OAppCore_init(address _delegate) internal onlyInitializing { __OAppCore_init_unchained(_delegate); } function __OAppCore_init_unchained(address _delegate) internal onlyInitializing { if (_delegate == address(0)) revert InvalidDelegate(); endpoint.setDelegate(_delegate); } /** * @notice Returns the peer address (OApp instance) associated with a specific endpoint. * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function peers(uint32 _eid) public view override returns (bytes32) { OAppCoreStorage storage $ = _getOAppCoreStorage(); return $.peers[_eid]; } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Only the owner/admin of the OApp can call this function. * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner { OAppCoreStorage storage $ = _getOAppCoreStorage(); $.peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { OAppCoreStorage storage $ = _getOAppCoreStorage(); bytes32 peer = $.peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) public onlyOwner { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IOAppReceiver, Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol"; import { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol"; /** * @title OAppReceiver * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers. */ abstract contract OAppReceiverUpgradeable is IOAppReceiver, OAppCoreUpgradeable { // Custom error message for when the caller is not the registered endpoint/ error OnlyEndpoint(address addr); // @dev The version of the OAppReceiver implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant RECEIVER_VERSION = 2; /** * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OAppReceiver_init(address _delegate) internal onlyInitializing { __OAppCore_init(_delegate); } function __OAppReceiver_init_unchained() internal onlyInitializing {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. * ie. this is a RECEIVE only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions. */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (0, RECEIVER_VERSION); } /** * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint. * @dev _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @dev _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata /*_origin*/, bytes calldata /*_message*/, address _sender ) public view virtual returns (bool) { return _sender == address(this); } /** * @notice Checks if the path initialization is allowed based on the provided origin. * @param origin The origin information containing the source endpoint and sender address. * @return Whether the path has been initialized. * * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received. * @dev This defaults to assuming if a peer has been set, its initialized. * Can be overridden by the OApp if there is other logic to determine this. */ function allowInitializePath(Origin calldata origin) public view virtual returns (bool) { return peers(origin.srcEid) == origin.sender; } /** * @notice Retrieves the next nonce for a given source endpoint and sender address. * @dev _srcEid The source endpoint ID. * @dev _sender The sender address. * @return nonce The next nonce. * * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement. * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered. * @dev This is also enforced by the OApp. * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0. */ function nextNonce(uint32, /*_srcEid*/ bytes32 /*_sender*/) public view virtual returns (uint64 nonce) { return 0; } /** * @dev Entry point for receiving messages or packets from the endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The payload of the received message. * @param _executor The address of the executor for the received message. * @param _extraData Additional arbitrary data provided by the corresponding executor. * * @dev Entry point for receiving msg/packet from the LayerZero endpoint. */ function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) public payable virtual { // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp. if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender); // Ensure that the sender matches the expected peer for the source endpoint. if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender); // Call the internal OApp implementation of lzReceive. _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppSenderUpgradeable is OAppCoreUpgradeable { using SafeERC20 for IERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OAppSender_init(address _delegate) internal onlyInitializing { __OAppCore_init(_delegate); } function __OAppSender_init_unchained() internal onlyInitializing {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote( uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken ) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return // solhint-disable-next-line check-send-result endpoint.send{ value: messageValue }( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value != _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppSenderUpgradeable, MessagingFee, MessagingReceipt } from "./OAppSenderUpgradeable.sol"; // @dev Import the 'Origin' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppReceiverUpgradeable, Origin } from "./OAppReceiverUpgradeable.sol"; import { OAppCoreUpgradeable } from "./OAppCoreUpgradeable.sol"; /** * @title OApp * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality. */ abstract contract OAppUpgradeable is OAppSenderUpgradeable, OAppReceiverUpgradeable { /** * @dev Constructor to initialize the OApp with the provided endpoint and owner. * @param _endpoint The address of the LOCAL LayerZero endpoint. */ constructor(address _endpoint) OAppCoreUpgradeable(_endpoint) {} /** * @dev Initializes the OApp with the provided delegate. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OApp_init(address _delegate) internal onlyInitializing { __OAppCore_init(_delegate); __OAppReceiver_init_unchained(); __OAppSender_init_unchained(); } function __OApp_init_unchained() internal onlyInitializing {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol implementation. * @return receiverVersion The version of the OAppReceiver.sol implementation. */ function oAppVersion() public pure virtual override(OAppSenderUpgradeable, OAppReceiverUpgradeable) returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, RECEIVER_VERSION); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { IPreCrime } from "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol"; import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol"; /** * @title OAppPreCrimeSimulator * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp. */ abstract contract OAppPreCrimeSimulatorUpgradeable is IOAppPreCrimeSimulator, OwnableUpgradeable { struct OAppPreCrimeSimulatorStorage { // The address of the preCrime implementation. address preCrime; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oappprecrimesimulator")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION = 0xefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600; function _getOAppPreCrimeSimulatorStorage() internal pure returns (OAppPreCrimeSimulatorStorage storage $) { assembly { $.slot := OAPP_PRE_CRIME_SIMULATOR_STORAGE_LOCATION } } /** * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OAppPreCrimeSimulator_init() internal onlyInitializing {} function __OAppPreCrimeSimulator_init_unchained() internal onlyInitializing {} function preCrime() external view override returns (address) { OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage(); return $.preCrime; } /** * @dev Retrieves the address of the OApp contract. * @return The address of the OApp contract. * * @dev The simulator contract is the base contract for the OApp by default. * @dev If the simulator is a separate contract, override this function. */ function oApp() external view virtual returns (address) { return address(this); } /** * @dev Sets the preCrime contract address. * @param _preCrime The address of the preCrime contract. */ function setPreCrime(address _preCrime) public virtual onlyOwner { OAppPreCrimeSimulatorStorage storage $ = _getOAppPreCrimeSimulatorStorage(); $.preCrime = _preCrime; emit PreCrimeSet(_preCrime); } /** * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results. * @param _packets An array of InboundPacket objects representing received packets to be delivered. * * @dev WARNING: MUST revert at the end with the simulation results. * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function, * WITHOUT actually executing them. */ function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual { for (uint256 i = 0; i < _packets.length; i++) { InboundPacket calldata packet = _packets[i]; // Ignore packets that are not from trusted peers. if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue; // @dev Because a verifier is calling this function, it doesnt have access to executor params: // - address _executor // - bytes calldata _extraData // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive(). // They are instead stubbed to default values, address(0) and bytes("") // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit, // which would cause the revert to be ignored. this.lzReceiveSimulate{ value: packet.value }( packet.origin, packet.guid, packet.message, packet.executor, packet.extraData ); } // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult(). revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult()); } /** * @dev Is effectively an internal function because msg.sender must be address(this). * Allows resetting the call stack for 'internal' calls. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier of the packet. * @param _message The message payload of the packet. * @param _executor The executor address for the packet. * @param _extraData Additional data for the packet. */ function lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable virtual { // @dev Ensure ONLY can be called 'internally'. if (msg.sender != address(this)) revert OnlySelf(); _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The GUID of the LayerZero message. * @param _message The LayerZero message. * @param _executor The address of the off-chain executor. * @param _extraData Arbitrary data passed by the msg executor. * * @dev Enables the preCrime simulator to mock sending lzReceive() messages, * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver. */ function _lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; /** * @dev checks if the specified peer is considered 'trusted' by the OApp. * @param _eid The endpoint Id to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. */ function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title IOAppCore */ interface IOAppCore { // Custom error messages error OnlyPeer(uint32 eid, bytes32 sender); error NoPeer(uint32 eid); error InvalidEndpointCall(); error InvalidDelegate(); // Event emitted when a peer (OApp) is set for a corresponding endpoint event PeerSet(uint32 eid, bytes32 peer); /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. */ function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion); /** * @notice Retrieves the LayerZero endpoint associated with the OApp. * @return iEndpoint The LayerZero endpoint as an interface. */ function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint); /** * @notice Retrieves the peer (OApp) associated with a corresponding endpoint. * @param _eid The endpoint ID. * @return peer The peer address (OApp instance) associated with the corresponding endpoint. */ function peers(uint32 _eid) external view returns (bytes32 peer); /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. */ function setPeer(uint32 _eid, bytes32 _peer) external; /** * @notice Sets the delegate address for the OApp Core. * @param _delegate The address of the delegate to be set. */ function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title IOAppMsgInspector * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents. */ interface IOAppMsgInspector { // Custom error message for inspection failure error InspectionFailed(bytes message, bytes options); /** * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid. * @param _message The message payload to be inspected. * @param _options Additional options or parameters for inspection. * @return valid A boolean indicating whether the inspection passed (true) or failed (false). * * @dev Optionally done as a revert, OR use the boolean provided to handle the failure. */ function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Struct representing enforced option parameters. */ struct EnforcedOptionParam { uint32 eid; // Endpoint ID uint16 msgType; // Message Type bytes options; // Additional options } /** * @title IOAppOptionsType3 * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options. */ interface IOAppOptionsType3 { // Custom error message for invalid options error InvalidOptions(bytes options); // Event emitted when enforced options are set event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions); /** * @notice Sets enforced options for specific endpoint and message type combinations. * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options. */ function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external; /** * @notice Combines options for a given endpoint and message type. * @param _eid The endpoint ID. * @param _msgType The OApp message type. * @param _extraOptions Additional options passed by the caller. * @return options The combination of caller specified options AND enforced options. */ function combineOptions( uint32 _eid, uint16 _msgType, bytes calldata _extraOptions ) external view returns (bytes memory options); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; interface IOAppReceiver is ILayerZeroReceiver { /** * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _message The lzReceive payload. * @param _sender The sender address. * @return isSender Is a valid sender. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OAppReceiver implementer. */ function isComposeMsgSender( Origin calldata _origin, bytes calldata _message, address _sender ) external view returns (bool isSender); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol"; /** * @title OAppCore * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations. */ abstract contract OAppCore is IOAppCore, Ownable { // The LayerZero endpoint associated with the given OApp ILayerZeroEndpointV2 public immutable endpoint; // Mapping to store peers associated with corresponding endpoints mapping(uint32 eid => bytes32 peer) public peers; /** * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate. * @param _endpoint The address of the LOCAL Layer Zero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. */ constructor(address _endpoint, address _delegate) { endpoint = ILayerZeroEndpointV2(_endpoint); if (_delegate == address(0)) revert InvalidDelegate(); endpoint.setDelegate(_delegate); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Only the owner/admin of the OApp can call this function. * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner { _setPeer(_eid, _peer); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function _setPeer(uint32 _eid, bytes32 _peer) internal virtual { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { bytes32 peer = peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) public onlyOwner { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppSender is OAppCore { using SafeERC20 for IERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote( uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken ) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return // solhint-disable-next-line check-send-result endpoint.send{ value: messageValue }( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value != _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers. // solhint-disable-next-line no-unused-import import { InboundPacket, Origin } from "../libs/Packet.sol"; /** * @title IOAppPreCrimeSimulator Interface * @dev Interface for the preCrime simulation functionality in an OApp. */ interface IOAppPreCrimeSimulator { // @dev simulation result used in PreCrime implementation error SimulationResult(bytes result); error OnlySelf(); /** * @dev Emitted when the preCrime contract address is set. * @param preCrimeAddress The address of the preCrime contract. */ event PreCrimeSet(address preCrimeAddress); /** * @dev Retrieves the address of the preCrime contract implementation. * @return The address of the preCrime contract. */ function preCrime() external view returns (address); /** * @dev Retrieves the address of the OApp contract. * @return The address of the OApp contract. */ function oApp() external view returns (address); /** * @dev Sets the preCrime contract address. * @param _preCrime The address of the preCrime contract. */ function setPreCrime(address _preCrime) external; /** * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result. * @param _packets An array of LayerZero InboundPacket objects representing received packets. */ function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable; /** * @dev checks if the specified peer is considered 'trusted' by the OApp. * @param _eid The endpoint Id to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. */ function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; struct PreCrimePeer { uint32 eid; bytes32 preCrime; bytes32 oApp; } // TODO not done yet interface IPreCrime { error OnlyOffChain(); // for simulate() error PacketOversize(uint256 max, uint256 actual); error PacketUnsorted(); error SimulationFailed(bytes reason); // for preCrime() error SimulationResultNotFound(uint32 eid); error InvalidSimulationResult(uint32 eid, bytes reason); error CrimeFound(bytes crime); function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory); function simulate( bytes[] calldata _packets, uint256[] calldata _packetMsgValues ) external payable returns (bytes memory); function buildSimulationResult() external view returns (bytes memory); function preCrime( bytes[] calldata _packets, uint256[] calldata _packetMsgValues, bytes[] calldata _simulations ) external; function version() external view returns (uint64 major, uint8 minor); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol"; /** * @title InboundPacket * @dev Structure representing an inbound packet received by the contract. */ struct InboundPacket { Origin origin; // Origin information of the packet. uint32 dstEid; // Destination endpointId of the packet. address receiver; // Receiver address for the packet. bytes32 guid; // Unique identifier of the packet. uint256 value; // msg.value of the packet. address executor; // Executor address for the packet. bytes message; // Message payload of the packet. bytes extraData; // Additional arbitrary data for the packet. } /** * @title PacketDecoder * @dev Library for decoding LayerZero packets. */ library PacketDecoder { using PacketV1Codec for bytes; /** * @dev Decode an inbound packet from the given packet data. * @param _packet The packet data to decode. * @return packet An InboundPacket struct representing the decoded packet. */ function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) { packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce()); packet.dstEid = _packet.dstEid(); packet.receiver = _packet.receiverB20(); packet.guid = _packet.guid(); packet.message = _packet.message(); } /** * @dev Decode multiple inbound packets from the given packet data and associated message values. * @param _packets An array of packet data to decode. * @param _packetMsgValues An array of associated message values for each packet. * @return packets An array of InboundPacket structs representing the decoded packets. */ function decode( bytes[] calldata _packets, uint256[] memory _packetMsgValues ) internal pure returns (InboundPacket[] memory packets) { packets = new InboundPacket[](_packets.length); for (uint256 i = 0; i < _packets.length; i++) { bytes calldata packet = _packets[i]; packets[i] = PacketDecoder.decode(packet); // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive. packets[i].value = _packetMsgValues[i]; } } }
// SPDX-LICENSE-IDENTIFIER: UNLICENSED pragma solidity ^0.8.20; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { FeeConfig, IFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IFee.sol"; /** * @title FeeUpgradeable * @notice Implements fee configuration and calculation. */ abstract contract FeeUpgradeable is IFee, Initializable, OwnableUpgradeable { uint16 public constant BPS_DENOMINATOR = 10_000; struct FeeStorage { uint16 defaultFeeBps; mapping(uint32 => FeeConfig) feeBps; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.fee")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant FEE_STORAGE_LOCATION = 0x0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de800; /** * @dev The init function is intentionally left empty and does not initialize Ownable. * This is to ensure that Ownable can be initialized in the child contract to accommodate * potential different versions of Ownable that might be used. */ function __Fee_init() internal onlyInitializing {} function __Fee_init_unchained() internal onlyInitializing {} function _getFeeStorage() internal pure returns (FeeStorage storage $) { assembly { $.slot := FEE_STORAGE_LOCATION } } /** * @dev Sets the default fee basis points (BPS) for all destinations. */ function setDefaultFeeBps(uint16 _feeBps) external onlyOwner { if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps(); FeeStorage storage $ = _getFeeStorage(); $.defaultFeeBps = _feeBps; emit DefaultFeeBpsSet(_feeBps); } /** * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID. */ function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external onlyOwner { if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps(); FeeStorage storage $ = _getFeeStorage(); $.feeBps[_dstEid] = FeeConfig(_feeBps, _enabled); emit FeeBpsSet(_dstEid, _feeBps, _enabled); } /** * @dev Returns the fee for a specific destination LayerZero EndpointV2 ID. */ function getFee(uint32 _dstEid, uint256 _amount) public view virtual returns (uint256) { uint16 bps = _getFeeBps(_dstEid); // @note If amount * bps < BPS_DENOMINATOR, there is no fee return bps == 0 ? 0 : (_amount * bps) / BPS_DENOMINATOR; } function _getFeeBps(uint32 _dstEid) internal view returns (uint16) { FeeStorage storage $ = _getFeeStorage(); FeeConfig memory config = $.feeBps[_dstEid]; return config.enabled ? config.feeBps : $.defaultFeeBps; } /** * @dev Returns the default fee. */ function defaultFeeBps() public view virtual returns (uint16) { FeeStorage storage $ = _getFeeStorage(); return $.defaultFeeBps; } /** * @dev Returns the configured fee for a given eid. */ function feeBps(uint32 _dstEid) public view virtual returns (FeeConfig memory) { FeeStorage storage $ = _getFeeStorage(); FeeConfig memory config = $.feeBps[_dstEid]; return config; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol"; import { FeeUpgradeable } from "./FeeUpgradeable.sol"; import { OFTAdapterUpgradeable } from "./OFTAdapterUpgradeable.sol"; /** * @title OFTAdapterFeeUpgradeable Contract * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality. * * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility. * @dev WARNING: ONLY 1 of these should exist for a given global mesh, * unless you make a NON-default implementation of OFT and needs to be done very carefully. * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD. */ abstract contract OFTAdapterFeeUpgradeable is OFTAdapterUpgradeable, FeeUpgradeable { using SafeERC20 for IERC20; struct OFTAdapterFeeStorage { uint256 feeBalance; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftadapterfee")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OFT_ADAPTER_FEE_STORAGE_LOCATION = 0x75ae803fc5bc34bf9750128bd6622421186811a8566aa9e660cbc56033db8c00; function _getOFTAdapterFeeStorage() internal pure returns (OFTAdapterFeeStorage storage $) { assembly { $.slot := OFT_ADAPTER_FEE_STORAGE_LOCATION } } function feeBalance() public view returns (uint256) { OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage(); return $.feeBalance; } event FeeWithdrawn(address indexed to, uint256 amountLD); error NoFeesToWithdraw(); /** * @dev Constructor for initializing the contract with token and endpoint addresses. * @param _token The address of the token. * @param _lzEndpoint The address of the LayerZero endpoint. * @dev _token must implement the IERC20 interface, and include a decimals() function. */ constructor(address _token, address _lzEndpoint) OFTAdapterUpgradeable(_token, _lzEndpoint) {} /** * @dev Initializes the OFTAdapter with the provided delegate. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OFTAdapterFee_init(address _delegate) internal onlyInitializing { __OFTAdapter_init(_delegate); __Fee_init(); } function __OFTAdapterFee_init_unchained() internal onlyInitializing {} /** * @notice Withdraws accumulated fees to a specified address. * @param _to The address to which the fees will be withdrawn. */ function withdrawFees(address _to) external onlyOwner { // @dev doesn't allow owner to pull from the locked assets of the contract, // only from accumulated fees OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage(); uint256 balance = $.feeBalance; if (balance == 0) revert NoFeesToWithdraw(); $.feeBalance = 0; innerToken.safeTransfer(_to, balance); emit FeeWithdrawn(_to, balance); } /** * @dev Calculates the amount to be sent and received after applying fees and checking for slippage. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; // @dev Apply the fee, then de-dust the amount afterwards. // This means the fee is taken from the amount before the dust is removed. uint256 fee = getFee(_dstEid, _amountLD); unchecked { amountReceivedLD = _removeDust(_amountLD - fee); } // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } /** * @dev Transfers the full amount from the sender's balance to the contract, * then burns the amount minus the fee from the contract leaving the fee locked in the contract. * @param _from The address to debit from. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); if (amountSentLD > amountReceivedLD) { // @dev Increment the total fees that can be withdrawn. // Fees include the dust resulting from the de-dust operation. OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage(); unchecked { $.feeBalance += (amountSentLD - amountReceivedLD); } } // @dev Lock tokens by moving them into this contract from the caller. innerToken.safeTransferFrom(_from, address(this), amountSentLD); } /** * @dev Credits tokens to the specified address. * @param _to The address to credit the tokens to. * @param _amountLD The amount of tokens to credit in local decimals. * @dev _srcEid The source chain ID. * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals. */ function _credit( address _to, uint256 _amountLD, uint32 // _srcEid ) internal virtual override returns (uint256 amountReceivedLD) { // @dev Unlock the tokens and transfer to the recipient. innerToken.safeTransfer(_to, _amountLD); // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol"; /** * @title OFTAdapter Contract * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality. * * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility. * @dev WARNING: ONLY 1 of these should exist for a given global mesh, * unless you make a NON-default implementation of OFT and needs to be done very carefully. * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD. */ abstract contract OFTAdapterUpgradeable is OFTCoreUpgradeable { using SafeERC20 for IERC20; IERC20 internal immutable innerToken; /** * @dev Constructor for the OFTAdapter contract. * @param _token The address of the ERC-20 token to be adapted. * @param _lzEndpoint The LayerZero endpoint address. * @dev _token must implement the IERC20 interface, and include a decimals() function. */ constructor( address _token, address _lzEndpoint ) OFTCoreUpgradeable(IERC20Metadata(_token).decimals(), _lzEndpoint) { innerToken = IERC20(_token); } /** * @dev Initializes the OFTAdapter with the provided delegate. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OFTAdapter_init(address _delegate) internal onlyInitializing { __OFTCore_init(_delegate); } function __OFTAdapter_init_unchained() internal onlyInitializing {} /** * @dev Retrieves the address of the underlying ERC20 implementation. * @return The address of the adapted ERC-20 token. * * @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract. */ function token() public view returns (address) { return address(innerToken); } /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev In the case of default OFTAdapter, approval is required. * @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval. */ function approvalRequired() external pure virtual returns (bool) { return true; } /** * @dev Burns tokens from the sender's specified balance, ie. pull method. * @param _from The address to debit from. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. * * @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract. * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountReceivedLD. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); // @dev Lock tokens by moving them into this contract from the caller. innerToken.safeTransferFrom(_from, address(this), amountSentLD); } /** * @dev Credits tokens to the specified address. * @param _to The address to credit the tokens to. * @param _amountLD The amount of tokens to credit in local decimals. * @dev _srcEid The source chain ID. * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals. * * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out. * IF the 'innerToken' applies something like a transfer fee, the default will NOT work... * a pre/post balance check will need to be done to calculate the amountReceivedLD. */ function _credit( address _to, uint256 _amountLD, uint32 /*_srcEid*/ ) internal virtual override returns (uint256 amountReceivedLD) { // @dev Unlock the tokens and transfer to the recipient. innerToken.safeTransfer(_to, _amountLD); // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { OAppUpgradeable, Origin } from "@layerzerolabs/oapp-evm-upgradeable/contracts/oapp/OAppUpgradeable.sol"; import { OAppOptionsType3Upgradeable } from "@layerzerolabs/oapp-evm-upgradeable/contracts/oapp/libs/OAppOptionsType3Upgradeable.sol"; import { IOAppMsgInspector } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol"; import { OAppPreCrimeSimulatorUpgradeable } from "@layerzerolabs/oapp-evm-upgradeable/contracts/precrime/OAppPreCrimeSimulatorUpgradeable.sol"; import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { OFTMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; /** * @title OFTCore * @dev Abstract contract for the OftChain (OFT) token. */ abstract contract OFTCoreUpgradeable is IOFT, OAppUpgradeable, OAppPreCrimeSimulatorUpgradeable, OAppOptionsType3Upgradeable { using OFTMsgCodec for bytes; using OFTMsgCodec for bytes32; struct OFTCoreStorage { // Address of an optional contract to inspect both 'message' and 'options' address msgInspector; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftcore")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OFT_CORE_STORAGE_LOCATION = 0x41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c00; // @notice Provides a conversion rate when swapping between denominations of SD and LD // - shareDecimals == SD == shared Decimals // - localDecimals == LD == local decimals // @dev Considers that tokens have different decimal amounts on various chains. // @dev eg. // For a token // - locally with 4 decimals --> 1.2345 => uint(12345) // - remotely with 2 decimals --> 1.23 => uint(123) // - The conversion rate would be 10 ** (4 - 2) = 100 // @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote, // you can only display 1.23 -> uint(123). // @dev To preserve the dust that would otherwise be lost on that conversion, // we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh uint256 public immutable decimalConversionRate; // @notice Msg types that are used to identify the various OFT operations. // @dev This can be extended in child contracts for non-default oft operations // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol. uint16 public constant SEND = 1; uint16 public constant SEND_AND_CALL = 2; event MsgInspectorSet(address inspector); function _getOFTCoreStorage() internal pure returns (OFTCoreStorage storage $) { assembly { $.slot := OFT_CORE_STORAGE_LOCATION } } /** * @dev Constructor. * @param _localDecimals The decimals of the token on the local chain (this chain). * @param _endpoint The address of the LayerZero endpoint. */ constructor(uint8 _localDecimals, address _endpoint) OAppUpgradeable(_endpoint) { if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals(); decimalConversionRate = 10 ** (_localDecimals - sharedDecimals()); } /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) { return (type(IOFT).interfaceId, 1); } /** * @dev Initializes the OFTCore contract. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OFTCore_init(address _delegate) internal onlyInitializing { __OApp_init(_delegate); __OAppPreCrimeSimulator_init(); __OAppOptionsType3_init(); } function __OFTCore_init_unchained() internal onlyInitializing {} function msgInspector() public view returns (address) { OFTCoreStorage storage $ = _getOFTCoreStorage(); return $.msgInspector; } /** * @dev Retrieves the shared decimals of the OFT. * @return The shared decimals of the OFT. * * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap * Lowest common decimal denominator between chains. * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64). * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller. * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615 */ function sharedDecimals() public pure virtual returns (uint8) { return 6; } /** * @dev Sets the message inspector address for the OFT. * @param _msgInspector The address of the message inspector. * * @dev This is an optional contract that can be used to inspect both 'message' and 'options'. * @dev Set it to address(0) to disable it, or set it to a contract address to enable it. */ function setMsgInspector(address _msgInspector) public virtual onlyOwner { OFTCoreStorage storage $ = _getOFTCoreStorage(); $.msgInspector = _msgInspector; emit MsgInspectorSet(_msgInspector); } /** * @notice Provides a quote for OFT-related operations. * @param _sendParam The parameters for the send operation. * @return oftLimit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return oftReceipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view virtual returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt) { uint256 minAmountLD = 0; // Unused in the default implementation. uint256 maxAmountLD = type(uint256).max; // Unused in the default implementation. oftLimit = OFTLimit(minAmountLD, maxAmountLD); // Unused in the default implementation; reserved for future complex fee details. oftFeeDetails = new OFTFeeDetail[](0); // @dev This is the same as the send() operation, but without the actual send. // - amountSentLD is the amount in local decimals that would be sent from the sender. // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance. // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does. (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView( _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); } /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return msgFee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend( SendParam calldata _sendParam, bool _payInLzToken ) external view virtual returns (MessagingFee memory msgFee) { // @dev mock the amount to receive, this is the same operation used in the send(). // The quote is as similar as possible to the actual send() operation. (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Calculates the LayerZero fee for the send() operation. return _quote(_sendParam.dstEid, message, options, _payInLzToken); } /** * @dev Executes the send operation. * @param _sendParam The parameters for the send operation. * @param _fee The calculated fee for the send() operation. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds. * @return msgReceipt The receipt for the send operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) { return _send(_sendParam, _fee, _refundAddress); } /** * @dev Internal function to execute send operations. * @param _sendParam The parameters for the send operation. * @param _fee The calculated LayerZero messaging fee from the send() operation. * @param _refundAddress The address to receive any excess funds from LayerZero fees. * @return msgReceipt The receipt from the LayerZero messaging library. * @return oftReceipt The OFT receipt information. */ function _send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) { // @dev Applies the token transfers regarding this send() operation. // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender. // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance. (uint256 amountSentLD, uint256 amountReceivedLD) = _debit( msg.sender, _sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid ); // @dev Builds the options and OFT message to quote in the endpoint. (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD); // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt. msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress); // @dev Formulate the OFT receipt. oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD); emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD); } /** * @dev Internal function to build the message and options. * @param _sendParam The parameters for the send() operation. * @param _amountLD The amount in local decimals. * @return message The encoded message. * @return options The encoded options. */ function _buildMsgAndOptions( SendParam calldata _sendParam, uint256 _amountLD ) internal view virtual returns (bytes memory message, bytes memory options) { bool hasCompose; // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is. (message, hasCompose) = OFTMsgCodec.encode( _sendParam.to, _toSD(_amountLD), // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote. // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01' _sendParam.composeMsg ); // @dev Change the msg type depending if its composed or not. uint16 msgType = hasCompose ? SEND_AND_CALL : SEND; // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3. options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions); OFTCoreStorage storage $ = _getOFTCoreStorage(); // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector. // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean address inspector = $.msgInspector; // caches the msgInspector to avoid potential double storage read if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options); } /** * @dev Internal function to handle the receive on the LayerZero endpoint. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The encoded message. * @dev _executor The address of the executor. * @dev _extraData Additional data. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address /*_executor*/, // @dev unused in the default implementation. bytes calldata /*_extraData*/ // @dev unused in the default implementation. ) internal virtual override { // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm) // Thus everything is bytes32() encoded in flight. address toAddress = _message.sendTo().bytes32ToAddress(); // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid); if (_message.isComposed()) { // @dev Proprietary composeMsg format for the OFT. bytes memory composeMsg = OFTComposeMsgCodec.encode( _origin.nonce, _origin.srcEid, amountReceivedLD, _message.composeMsg() ); // @dev Stores the lzCompose payload that will be executed in a separate tx. // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains. // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed. // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive. // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0. endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg); } emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD); } /** * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive. * @param _origin The origin information. * - srcEid: The source chain endpoint ID. * - sender: The sender address from the src chain. * - nonce: The nonce of the LayerZero message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The LayerZero message. * @param _executor The address of the off-chain executor. * @param _extraData Arbitrary data passed by the msg executor. * * @dev Enables the preCrime simulator to mock sending lzReceive() messages, * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver. */ function _lzReceiveSimulate( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual override { _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Check if the peer is considered 'trusted' by the OApp. * @param _eid The endpoint ID to check. * @param _peer The peer to check. * @return Whether the peer passed is considered 'trusted' by the OApp. * * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source. */ function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) { return peers(_eid) == _peer; } /** * @dev Internal function to remove dust from the given local decimal amount. * @param _amountLD The amount in local decimals. * @return amountLD The amount after removing dust. * * @dev Prevents the loss of dust when moving amounts between chains with different decimals. * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100). */ function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) { return (_amountLD / decimalConversionRate) * decimalConversionRate; } /** * @dev Internal function to convert an amount from shared decimals into local decimals. * @param _amountSD The amount in shared decimals. * @return amountLD The amount in local decimals. */ function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) { return _amountSD * decimalConversionRate; } /** * @dev Internal function to convert an amount from local decimals into shared decimals. * @param _amountLD The amount in local decimals. * @return amountSD The amount in shared decimals. * * @dev Reverts if the _amountLD in shared decimals overflows uint64. * @dev eg. uint(2**64 + 123) with a conversion rate of 1 wraps around 2**64 to uint(123). */ function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) { uint256 _amountSD = _amountLD / decimalConversionRate; if (_amountSD > type(uint64).max) revert AmountSDOverflowed(_amountSD); return uint64(_amountSD); } /** * @dev Internal function to mock the amount mutation from a OFT debit() operation. * @param _amountLD The amount to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @dev _dstEid The destination endpoint ID. * @return amountSentLD The amount sent, in local decimals. * @return amountReceivedLD The amount to be received on the remote chain, in local decimals. * * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote. */ function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 /*_dstEid*/ ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) { // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token. amountSentLD = _removeDust(_amountLD); // @dev The amount to send is the same as amount received in the default implementation. amountReceivedLD = amountSentLD; // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } /** * @dev Internal function to perform a debit operation. * @param _from The address to debit from. * @param _amountLD The amount to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination endpoint ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD); /** * @dev Internal function to perform a credit operation. * @param _to The address to credit. * @param _amountLD The amount to credit in local decimals. * @param _srcEid The source endpoint ID. * @return amountReceivedLD The amount ACTUALLY received in local decimals. * * @dev Defined here but are intended to be overriden depending on the OFT implementation. * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD. */ function _credit( address _to, uint256 _amountLD, uint32 _srcEid ) internal virtual returns (uint256 amountReceivedLD); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { FeeUpgradeable } from "./FeeUpgradeable.sol"; import { OFTUpgradeable } from "./OFTUpgradeable.sol"; /** * @title OFTFeeUpgradeable Contract * @notice Upgradeable OFT with fees. */ abstract contract OFTFeeUpgradeable is OFTUpgradeable, FeeUpgradeable { struct OFTFeeStorage { uint256 feeBalance; } // keccak256(abi.encode(uint256(keccak256("layerzerov2.storage.oftfee")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OFT_FEE_STORAGE_LOCATION = 0x68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b342200; function _getOFTFeeStorage() internal pure returns (OFTFeeStorage storage $) { assembly { $.slot := OFT_FEE_STORAGE_LOCATION } } function feeBalance() public view returns (uint256) { OFTFeeStorage storage $ = _getOFTFeeStorage(); return $.feeBalance; } event FeeWithdrawn(address indexed to, uint256 amountLD); error NoFeesToWithdraw(); /** * @dev Constructor for initializing the contract with LayerZero endpoint address. * @param _lzEndpoint The address of the LayerZero endpoint. */ constructor(address _lzEndpoint) OFTUpgradeable(_lzEndpoint) {} /** * @dev Initializes the OFTFeeUpgradeable contract. * @param _name The name of the OFT. * @param _symbol The symbol of the OFT. * @param _delegate The address of the LayerZero delegate. */ function __OFTFee_init( string memory _name, string memory _symbol, address _delegate ) internal onlyInitializing { __OFT_init(_name, _symbol, _delegate); __Fee_init(); } /** * @dev Unchained initialization function for the contract. */ function __OFTFee_init_unchained() internal onlyInitializing {} /** * @dev Calculates the amount to be sent and received after applying fees and checking for slippage. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debitView( uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; // @dev Apply the fee, then de-dust the amount afterwards. // This means the fee is taken from the amount before the dust is removed. uint256 fee = getFee(_dstEid, _amountLD); unchecked { amountReceivedLD = _removeDust(_amountLD - fee); } // @dev Check for slippage. if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } /** * @dev Debits the sender's account for the full amount with fees and burns amount minus fees. * @param _from The address of the sender. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain endpoint ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the destination chain. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); if (amountSentLD > amountReceivedLD) { // @dev Increment the total fees that can be withdrawn. // Fees include the dust resulting from the de-dust operation. OFTFeeStorage storage $ = _getOFTFeeStorage(); unchecked { uint256 fee = amountSentLD - amountReceivedLD; $.feeBalance += fee; _transfer(_from, address(this), fee); } } _burn(_from, amountReceivedLD); } /** * @notice Withdraws accumulated fees to a specified address. * @param _to The address to which the fees will be withdrawn. */ function withdrawFees(address _to) external onlyOwner { OFTFeeStorage storage $ = _getOFTFeeStorage(); uint256 balance = $.feeBalance; if (balance == 0) revert NoFeesToWithdraw(); $.feeBalance = 0; _transfer(address(this), _to, balance); emit FeeWithdrawn(_to, balance); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import { IOFT, OFTCoreUpgradeable } from "./OFTCoreUpgradeable.sol"; /** * @title OFT Contract * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract. */ abstract contract OFTUpgradeable is OFTCoreUpgradeable, ERC20Upgradeable { /** * @dev Constructor for the OFT contract. * @param _lzEndpoint The LayerZero endpoint address. */ constructor(address _lzEndpoint) OFTCoreUpgradeable(decimals(), _lzEndpoint) {} /** * @dev Initializes the OFT with the provided name, symbol, and delegate. * @param _name The name of the OFT. * @param _symbol The symbol of the OFT. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to * accommodate the different version of Ownable. */ function __OFT_init(string memory _name, string memory _symbol, address _delegate) internal onlyInitializing { __ERC20_init(_name, _symbol); __OFTCore_init(_delegate); } function __OFT_init_unchained() internal onlyInitializing {} /** * @dev Retrieves the address of the underlying ERC20 implementation. * @return The address of the OFT token. * * @dev In the case of OFT, address(this) and erc20 are the same contract. */ function token() public view returns (address) { return address(this); } /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev In the case of OFT where the contract IS the token, approval is NOT required. */ function approvalRequired() external pure virtual returns (bool) { return false; } /** * @dev Burns tokens from the sender's specified balance. * @param _from The address to debit the tokens from. * @param _amountLD The amount of tokens to send in local decimals. * @param _minAmountLD The minimum amount to send in local decimals. * @param _dstEid The destination chain ID. * @return amountSentLD The amount sent in local decimals. * @return amountReceivedLD The amount received in local decimals on the remote. */ function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90, // therefore amountSentLD CAN differ from amountReceivedLD. // @dev Default OFT burns on src. _burn(_from, amountSentLD); } /** * @dev Credits tokens to the specified address. * @param _to The address to credit the tokens to. * @param _amountLD The amount of tokens to credit in local decimals. * @dev _srcEid The source chain ID. * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals. */ function _credit( address _to, uint256 _amountLD, uint32 /*_srcEid*/ ) internal virtual override returns (uint256 amountReceivedLD) { if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0) // @dev Default OFT mints on dst. _mint(_to, _amountLD); // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD. return _amountLD; } }
// SPDX-LICENSE-IDENTIFIER: MIT pragma solidity ^0.8.0; struct FeeConfig { uint16 feeBps; bool enabled; } /** * @title Fee interface. * @notice A generic interface for collecting fees. */ interface IFee { // errors error InvalidBps(); error InvalidFeeOwner(); // events event FeeBpsSet(uint32 dstEid, uint16 feeBps, bool enabled); event DefaultFeeBpsSet(uint16 feeBps); // setters /** * @dev Sets the default fee basis points (BPS) for all destinations. */ function setDefaultFeeBps(uint16 _feeBps) external; /** * @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID. */ function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { MessagingReceipt, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol"; /** * @dev Struct representing token parameters for the OFT send() operation. */ struct SendParam { uint32 dstEid; // Destination endpoint ID. bytes32 to; // Recipient address. uint256 amountLD; // Amount to send in local decimals. uint256 minAmountLD; // Minimum amount to send in local decimals. bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message. bytes composeMsg; // The composed message for the send() operation. bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. } /** * @dev Struct representing OFT limit information. * @dev These amounts can change dynamically and are up the specific oft implementation. */ struct OFTLimit { uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient. uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient. } /** * @dev Struct representing OFT receipt information. */ struct OFTReceipt { uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals. // @dev In non-default implementations, the amountReceivedLD COULD differ from this value. uint256 amountReceivedLD; // Amount of tokens to be received on the remote side. } /** * @dev Struct representing OFT fee details. * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI. */ struct OFTFeeDetail { int256 feeAmountLD; // Amount of the fee in local decimals. string description; // Description of the fee. } /** * @title IOFT * @dev Interface for the OftChain (OFT) token. * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well. * @dev This specific interface ID is '0x02e49c2c'. */ interface IOFT { // Custom error messages error InvalidLocalDecimals(); error SlippageExceeded(uint256 amountLD, uint256 minAmountLD); error AmountSDOverflowed(uint256 amountSD); // Events event OFTSent( bytes32 indexed guid, // GUID of the OFT message. uint32 dstEid, // Destination Endpoint ID. address indexed fromAddress, // Address of the sender on the src chain. uint256 amountSentLD, // Amount of tokens sent in local decimals. uint256 amountReceivedLD // Amount of tokens received in local decimals. ); event OFTReceived( bytes32 indexed guid, // GUID of the OFT message. uint32 srcEid, // Source Endpoint ID. address indexed toAddress, // Address of the recipient on the dst chain. uint256 amountReceivedLD // Amount of tokens received in local decimals. ); /** * @notice Retrieves interfaceID and the version of the OFT. * @return interfaceId The interface ID. * @return version The version. * * @dev interfaceId: This specific interface ID is '0x02e49c2c'. * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs. * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1) */ function oftVersion() external view returns (bytes4 interfaceId, uint64 version); /** * @notice Retrieves the address of the token associated with the OFT. * @return token The address of the ERC20 token implementation. */ function token() external view returns (address); /** * @notice Indicates whether the OFT contract requires approval of the 'token()' to send. * @return requiresApproval Needs approval of the underlying token implementation. * * @dev Allows things like wallet implementers to determine integration requirements, * without understanding the underlying token implementation. */ function approvalRequired() external view returns (bool); /** * @notice Retrieves the shared decimals of the OFT. * @return sharedDecimals The shared decimals of the OFT. */ function sharedDecimals() external view returns (uint8); /** * @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation. * @param _sendParam The parameters for the send operation. * @return limit The OFT limit information. * @return oftFeeDetails The details of OFT fees. * @return receipt The OFT receipt information. */ function quoteOFT( SendParam calldata _sendParam ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory); /** * @notice Provides a quote for the send() operation. * @param _sendParam The parameters for the send() operation. * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token. * @return fee The calculated LayerZero messaging fee from the send() operation. * * @dev MessagingFee: LayerZero msg fee * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. */ function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory); /** * @notice Executes the send() operation. * @param _sendParam The parameters for the send operation. * @param _fee The fee information supplied by the caller. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess funds from fees etc. on the src. * @return receipt The LayerZero messaging receipt from the send() operation. * @return oftReceipt The OFT receipt information. * * @dev MessagingReceipt: LayerZero msg receipt * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function send( SendParam calldata _sendParam, MessagingFee calldata _fee, address _refundAddress ) external payable returns (MessagingReceipt memory, OFTReceipt memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library OFTComposeMsgCodec { // Offset constants for decoding composed messages uint8 private constant NONCE_OFFSET = 8; uint8 private constant SRC_EID_OFFSET = 12; uint8 private constant AMOUNT_LD_OFFSET = 44; uint8 private constant COMPOSE_FROM_OFFSET = 76; /** * @dev Encodes a OFT composed message. * @param _nonce The nonce value. * @param _srcEid The source endpoint ID. * @param _amountLD The amount in local decimals. * @param _composeMsg The composed message. * @return _msg The encoded Composed message. */ function encode( uint64 _nonce, uint32 _srcEid, uint256 _amountLD, bytes memory _composeMsg // 0x[composeFrom][composeMsg] ) internal pure returns (bytes memory _msg) { _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg); } /** * @dev Retrieves the nonce for the composed message. * @param _msg The message. * @return The nonce value. */ function nonce(bytes calldata _msg) internal pure returns (uint64) { return uint64(bytes8(_msg[:NONCE_OFFSET])); } /** * @dev Retrieves the source endpoint ID for the composed message. * @param _msg The message. * @return The source endpoint ID. */ function srcEid(bytes calldata _msg) internal pure returns (uint32) { return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET])); } /** * @dev Retrieves the amount in local decimals from the composed message. * @param _msg The message. * @return The amount in local decimals. */ function amountLD(bytes calldata _msg) internal pure returns (uint256) { return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET])); } /** * @dev Retrieves the composeFrom value from the composed message. * @param _msg The message. * @return The composeFrom value. */ function composeFrom(bytes calldata _msg) internal pure returns (bytes32) { return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]); } /** * @dev Retrieves the composed message. * @param _msg The message. * @return The composed message. */ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) { return _msg[COMPOSE_FROM_OFFSET:]; } /** * @dev Converts an address to bytes32. * @param _addr The address to convert. * @return The bytes32 representation of the address. */ function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } /** * @dev Converts bytes32 to an address. * @param _b The bytes32 value to convert. * @return The address representation of bytes32. */ function bytes32ToAddress(bytes32 _b) internal pure returns (address) { return address(uint160(uint256(_b))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library OFTMsgCodec { // Offset constants for encoding and decoding OFT messages uint8 private constant SEND_TO_OFFSET = 32; uint8 private constant SEND_AMOUNT_SD_OFFSET = 40; /** * @dev Encodes an OFT LayerZero message. * @param _sendTo The recipient address. * @param _amountShared The amount in shared decimals. * @param _composeMsg The composed message. * @return _msg The encoded message. * @return hasCompose A boolean indicating whether the message has a composed payload. */ function encode( bytes32 _sendTo, uint64 _amountShared, bytes memory _composeMsg ) internal view returns (bytes memory _msg, bool hasCompose) { hasCompose = _composeMsg.length > 0; // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src. _msg = hasCompose ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg) : abi.encodePacked(_sendTo, _amountShared); } /** * @dev Checks if the OFT message is composed. * @param _msg The OFT message. * @return A boolean indicating whether the message is composed. */ function isComposed(bytes calldata _msg) internal pure returns (bool) { return _msg.length > SEND_AMOUNT_SD_OFFSET; } /** * @dev Retrieves the recipient address from the OFT message. * @param _msg The OFT message. * @return The recipient address. */ function sendTo(bytes calldata _msg) internal pure returns (bytes32) { return bytes32(_msg[:SEND_TO_OFFSET]); } /** * @dev Retrieves the amount in shared decimals from the OFT message. * @param _msg The OFT message. * @return The amount in shared decimals. */ function amountSD(bytes calldata _msg) internal pure returns (uint64) { return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET])); } /** * @dev Retrieves the composed message from the OFT message. * @param _msg The OFT message. * @return The composed message. */ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) { return _msg[SEND_AMOUNT_SD_OFFSET:]; } /** * @dev Converts an address to bytes32. * @param _addr The address to convert. * @return The bytes32 representation of the address. */ function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } /** * @dev Converts bytes32 to an address. * @param _b The bytes32 value to convert. * @return The address representation of bytes32. */ function bytes32ToAddress(bytes32 _b) internal pure returns (address) { return address(uint160(uint256(_b))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reinitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. * * NOTE: Consider following the ERC-7201 formula to derive storage locations. */ function _initializableStorageSlot() internal pure virtual returns (bytes32) { return INITIALIZABLE_STORAGE; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { bytes32 slot = _initializableStorageSlot(); assembly { $.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; string _name; string _symbol; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage $) { assembly { $.slot := ERC20StorageLocation } } /** * @dev Sets the values for {name} and {symbol}. * * Both values are immutable: they can only be set once during construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC20Storage storage $ = _getERC20Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /// @inheritdoc IERC20 function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /// @inheritdoc IERC20 function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /// @inheritdoc IERC20 function allowance(address owner, address spender) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply += value; } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner`'s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance < type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol) pragma solidity >=0.8.4; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol) pragma solidity >=0.6.2; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol) pragma solidity >=0.4.16; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol) pragma solidity >=0.4.16; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * Both values are immutable: they can only be set once during construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /// @inheritdoc IERC20 function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /// @inheritdoc IERC20 function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /// @inheritdoc IERC20 function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner`'s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance < type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity >=0.6.2; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol) pragma solidity >=0.4.16; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol) pragma solidity >=0.4.16; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; contract Empty is Initializable { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize() public initializer { } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract GGUSD is ERC20 { address public minter; // 指定的mint权限账户 constructor(address _minter) ERC20("GGUSD", "GGUSD") { minter = _minter; } function mint(address to, uint256 amount) public { require(msg.sender == minter, "Only minter can mint tokens"); _mint(to, amount); } function decimals() public override view virtual returns (uint8) { return 6; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import {OFTAdapterFeeUpgradeable} from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTAdapterFeeUpgradeable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract GGUSDOFTAdapter is OFTAdapterFeeUpgradeable { using SafeERC20 for IERC20; address private feeAddress; mapping(address => bool) private whitelist; event FeeAddress(address feeAddress); event WhitelistUpdated(address indexed account, bool isWhitelisted); constructor( address _token, address _lzEndpoint ) OFTAdapterFeeUpgradeable(_token, _lzEndpoint){ _disableInitializers(); } function initialize( address _delegate ) public initializer { __OFTAdapter_init(_delegate); __Ownable_init(_delegate); feeAddress = address(0); } function setFeeAddress(address _feeAddress) external onlyOwner { feeAddress = _feeAddress; emit FeeAddress(feeAddress); } function getFeeAddress() public view virtual returns (address) { return feeAddress; } function addToWhitelist(address _account) external onlyOwner { require(!whitelist[_account], "Already whitelisted"); whitelist[_account] = true; emit WhitelistUpdated(_account, true); } function removeFromWhitelist(address _account) external onlyOwner { require(whitelist[_account], "Not whitelisted"); whitelist[_account] = false; emit WhitelistUpdated(_account, false); } function isWhitelisted(address _account) public view returns (bool) { return whitelist[_account]; } function _debit( address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = whitelist[_from] ? _debitViewNoFee(_amountLD, _minAmountLD) : _debitView(_amountLD, _minAmountLD, _dstEid); if (amountReceivedLD > amountSentLD) { revert("Amount received cannot be greater than amount sent"); } uint256 fee = amountSentLD - amountReceivedLD; if (feeAddress == address(0)) { if (fee > 0) { OFTAdapterFeeStorage storage $ = _getOFTAdapterFeeStorage(); unchecked { $.feeBalance += fee; } } innerToken.safeTransferFrom(_from, address(this), amountSentLD); } else { // transfer fee to special account if (fee > 0) { innerToken.safeTransferFrom(_from, feeAddress, fee); } innerToken.safeTransferFrom(_from, address(this), amountReceivedLD); } } function _debitViewNoFee( uint256 _amountLD, uint256 _minAmountLD ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) { amountSentLD = _amountLD; unchecked { amountReceivedLD = _removeDust(_amountLD); } if (amountReceivedLD < _minAmountLD) { revert SlippageExceeded(amountReceivedLD, _minAmountLD); } } function sharedDecimals() public pure override virtual returns (uint8) { return 6; } }
pragma solidity ^0.8.22; // optimization enabled, 99999 runs, evm: petersburg /** * @title Immutable Create2 Contract Factory * @author 0age * @notice This contract provides a safeCreate2 function that takes a salt value * and a block of initialization code as arguments and passes them into inline * assembly. The contract prevents redeploys by maintaining a mapping of all * contracts that have already been deployed, and prevents frontrunning or other * collisions by requiring that the first 20 bytes of the salt are equal to the * address of the caller (this can be bypassed by setting the first 20 bytes to * the null address). There is also a view function that computes the address of * the contract that will be created when submitting a given salt or nonce along * with a given block of initialization code. * @dev This contract has not yet been fully tested or audited - proceed with * caution and please share any exploits or optimizations you discover. */ contract ImmutableCreate2Factory { // mapping to track which addresses have already been deployed. mapping(address => bool) private _deployed; /** * @dev Create a contract using CREATE2 by submitting a given salt or nonce * along with the initialization code for the contract. Note that the first 20 * bytes of the salt must match those of the calling address, which prevents * contract creation events from being submitted by unintended parties. * @param salt bytes32 The nonce that will be passed into the CREATE2 call. * @param initializationCode bytes The initialization code that will be passed * into the CREATE2 call. * @return deploymentAddress Address of the contract that will be created, or the null address * if a contract already exists at that address. */ function safeCreate2( bytes32 salt, bytes calldata initializationCode ) external payable containsCaller(salt) returns (address deploymentAddress) { // move the initialization code from calldata to memory. bytes memory initCode = initializationCode; // determine the target address for contract deployment. address targetDeploymentAddress = address( uint160( // downcast to match the address type. uint256( // convert to uint to truncate upper digits. keccak256( // compute the CREATE2 hash using 4 inputs. abi.encodePacked( // pack all inputs to the hash together. hex"ff", // start with 0xff to distinguish from RLP. address(this), // this contract will be the caller. salt, // pass in the supplied salt value. keccak256( // pass in the hash of initialization code. abi.encodePacked( initCode ) ) ) ) ) ) ); // ensure that a contract hasn't been previously deployed to target address. require( !_deployed[targetDeploymentAddress], "Invalid contract creation - contract has already been deployed." ); // using inline assembly: load data and length of data, then call CREATE2. assembly { // solhint-disable-line let encoded_data := add(0x20, initCode) // load initialization code. let encoded_size := mload(initCode) // load the init code's length. deploymentAddress := create2( // call CREATE2 with 4 arguments. callvalue(), // forward any attached value. encoded_data, // pass in initialization code. encoded_size, // pass in init code's length. salt // pass in the salt value. ) } // check address against target to ensure that deployment was successful. require( deploymentAddress == targetDeploymentAddress, "Failed to deploy contract using provided salt and initialization code." ); // record the deployment of the contract to prevent redeploys. _deployed[deploymentAddress] = true; } /** * @dev Compute the address of the contract that will be created when * submitting a given salt or nonce to the contract along with the contract's * initialization code. The CREATE2 address is computed in accordance with * EIP-1014, and adheres to the formula therein of * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when * performing the computation. The computed address is then checked for any * existing contract code - if so, the null address will be returned instead. * @param salt bytes32 The nonce passed into the CREATE2 address calculation. * @param initCode bytes The contract initialization code to be used. * that will be passed into the CREATE2 address calculation. * @return deploymentAddress Address of the contract that will be created, or the null address * if a contract has already been deployed to that address. */ function findCreate2Address( bytes32 salt, bytes calldata initCode ) external view returns (address deploymentAddress) { // determine the address where the contract will be deployed. deploymentAddress = address( uint160( // downcast to match the address type. uint256( // convert to uint to truncate upper digits. keccak256( // compute the CREATE2 hash using 4 inputs. abi.encodePacked( // pack all inputs to the hash together. hex"ff", // start with 0xff to distinguish from RLP. address(this), // this contract will be the caller. salt, // pass in the supplied salt value. keccak256( // pass in the hash of initialization code. abi.encodePacked( initCode ) ) ) ) ) ) ); // return null address to signify failure if contract has been deployed. if (_deployed[deploymentAddress]) { return address(0); } } /** * @dev Compute the address of the contract that will be created when * submitting a given salt or nonce to the contract along with the keccak256 * hash of the contract's initialization code. The CREATE2 address is computed * in accordance with EIP-1014, and adheres to the formula therein of * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when * performing the computation. The computed address is then checked for any * existing contract code - if so, the null address will be returned instead. * @param salt bytes32 The nonce passed into the CREATE2 address calculation. * @param initCodeHash bytes32 The keccak256 hash of the initialization code * that will be passed into the CREATE2 address calculation. * @return deploymentAddress Address of the contract that will be created, or the null address * if a contract has already been deployed to that address. */ function findCreate2AddressViaHash( bytes32 salt, bytes32 initCodeHash ) external view returns (address deploymentAddress) { // determine the address where the contract will be deployed. deploymentAddress = address( uint160( // downcast to match the address type. uint256( // convert to uint to truncate upper digits. keccak256( // compute the CREATE2 hash using 4 inputs. abi.encodePacked( // pack all inputs to the hash together. hex"ff", // start with 0xff to distinguish from RLP. address(this), // this contract will be the caller. salt, // pass in the supplied salt value. initCodeHash // pass in the hash of initialization code. ) ) ) ) ); // return null address to signify failure if contract has been deployed. if (_deployed[deploymentAddress]) { return address(0); } } /** * @dev Determine if a contract has already been deployed by the factory to a * given address. * @param deploymentAddress address The contract address to check. * @return True if the contract has been deployed, false otherwise. */ function hasBeenDeployed( address deploymentAddress ) external view returns (bool) { // determine if a contract has been deployed to the provided address. return _deployed[deploymentAddress]; } /** * @dev Modifier to ensure that the first 20 bytes of a submitted salt match * those of the calling account. This provides protection against the salt * being stolen by frontrunners or other attackers. The protection can also be * bypassed if desired by setting each of the first 20 bytes to zero. * @param salt bytes32 The salt value to check against the calling address. */ modifier containsCaller(bytes32 salt) { // prevent contract submissions from being stolen from tx.pool by requiring // that the first 20 bytes of the submitted salt match msg.sender. require( (address(bytes20(salt)) == msg.sender) || (bytes20(salt) == bytes20(0)), "Invalid salt - first 20 bytes of the salt must match calling address." ); _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol) pragma solidity ^0.8.0; import {TransparentUpgradeableProxy} from "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol"; import {Ownable} from "hardhat-deploy/solc_0.8/openzeppelin/access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. */ contract ProxyAdmin is Ownable { constructor (address initialOwner) Ownable(initialOwner) {} /** * @dev Returns the current implementation of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("implementation()")) == 0x5c60da1b (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); require(success); return abi.decode(returndata, (address)); } /** * @dev Returns the current admin of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("admin()")) == 0xf851a440 (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); require(success); return abi.decode(returndata, (address)); } /** * @dev Changes the admin of `proxy` to `newAdmin`. * * Requirements: * * - This contract must be the current admin of `proxy`. */ function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { proxy.changeAdmin(newAdmin); } /** * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { proxy.upgradeTo(implementation); } /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See * {TransparentUpgradeableProxy-upgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgradeAndCall( TransparentUpgradeableProxy proxy, address implementation, bytes memory data ) public payable virtual onlyOwner { proxy.upgradeToAndCall{value: msg.value}(implementation, data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); } interface ITransparentUpgradeableProxy is IERC1967 { function upgradeToAndCall(address, bytes calldata) external payable; } contract ProxyAdminV5 { string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev Sets the initial owner who can perform upgrades. */ constructor(address initialOwner) {} /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. * - If `data` is empty, `msg.value` must be zero. */ function upgradeAndCall( address proxy, address implementation, bytes memory data ) public payable virtual { // proxy.upgradeToAndCall{value: msg.value}(implementation, data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 (address initialOwner) { _transferOwnership(initialOwner); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializating the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967Upgrade { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view virtual returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require(Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract"); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overriden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; import "../ERC1967/ERC1967Proxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. */ constructor( address _logic, address admin_, bytes memory _data ) payable ERC1967Proxy(_logic, _data) { assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev Returns the current admin. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function admin() external ifAdmin returns (address admin_) { admin_ = _getAdmin(); } /** * @dev Returns the current implementation. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function implementation() external ifAdmin returns (address implementation_) { implementation_ = _implementation(); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. * * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. */ function changeAdmin(address newAdmin) external virtual ifAdmin { _changeAdmin(newAdmin); } /** * @dev Upgrade the implementation of the proxy. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeToAndCall(newImplementation, bytes(""), false); } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. */ function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { _upgradeToAndCall(newImplementation, data, true); } /** * @dev Returns the current admin. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. */ function _beforeFallback() internal virtual override { require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); super._beforeFallback(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly { r.slot := slot } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_lzEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amountSD","type":"uint256"}],"name":"AmountSDOverflowed","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidBps","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidFeeOwner","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[],"name":"NoFeesToWithdraw","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"DefaultFeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeAddress","type":"address"}],"name":"FeeAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"FeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"}],"name":"FeeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromBalanceAfterTransfer","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toBalanceAfterTransfer","type":"uint256"}],"name":"TransferEx","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"WhitelistUpdated","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"}],"name":"feeBps","outputs":[{"components":[{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"bool","name":"enabled","type":"bool"}],"internalType":"struct FeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_delegate","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBps","type":"uint16"}],"name":"setDefaultFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint16","name":"_feeBps","type":"uint16"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200441938038062004419833981016040819052620000349162000147565b6001600160a01b0381166080528080600681620000536006836200018f565b6200006090600a620002a8565b60a05250620000739250506200007a9050565b50620002b9565b6000620000866200011c565b805490915068010000000000000000900460ff1615620000b95760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001195780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b6000602082840312156200015a57600080fd5b81516001600160a01b03811681146200017257600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111562000141576200014162000179565b600181815b80851115620001ec578160001904821115620001d057620001d062000179565b80851615620001de57918102915b93841c9390800290620001b0565b509250929050565b600082620002055750600162000141565b81620002145750600062000141565b81600181146200022d5760028114620002385762000258565b600191505062000141565b60ff8411156200024c576200024c62000179565b50506001821b62000141565b5060208310610133831016604e8410600b84101617156200027d575081810a62000141565b620002898383620001ab565b8060001904821115620002a057620002a062000179565b029392505050565b60006200017260ff841683620001f4565b60805160a0516140f462000325600039600081816109430152818161260e0152818161268301526127ec01526000818161079201528181610e6801528181611aa801528181611ea2015281816121c701528181612a1f01528181612d910152612e4a01526140f46000f3fe60806040526004361061036b5760003560e01c806370a08231116101c6578063bb0b6a53116100f7578063d424388511610095578063e43252d71161006f578063e43252d714610b11578063f2fde38b14610b31578063fc0c546a146106e9578063ff7bd03d14610b5157600080fd5b8063d424388514610abb578063dd62ed3e14610adb578063e1a4521814610afb57600080fd5b8063bd815db0116100d1578063bd815db014610a54578063c7c7f5b314610a67578063ca5eb5e114610a88578063d045a0dc14610aa857600080fd5b8063bb0b6a53146109ce578063bc70b35414610a0e578063bcae25a414610a2e57600080fd5b80638da5cb5b116101645780639f68b9641161013e5780639f68b96414610965578063a9059cbb14610979578063b731ea0a14610999578063b98bd070146109ae57600080fd5b80638da5cb5b1461090757806395d89b411461091c578063963efcaa1461093157600080fd5b806382413eac116101a057806382413eac14610898578063857749b0146105605780638705fcd4146108c75780638ab1d681146108e757600080fd5b806370a0823114610828578063715018a6146108485780637d25a05e1461085d57600080fd5b80633194c180116102a05780635535d4611161023e5780635e280f11116102185780635e280f111461078057806360b71d4e146107b45780636db7bcdb146107e85780636fc1b31e1461080857600080fd5b80635535d461146106fc5780635a0dfe4d1461071c5780635bf9c2261461076057600080fd5b80633b6f743b1161027a5780633b6f743b1461067e5780634488b652146106ab5780634e7ceacb146106cb57806352ae2879146106e957600080fd5b80633194c1801461057c5780633400288b146106255780633af32abf1461064557600080fd5b8063156a0d0f1161030d57806318160ddd116102e757806318160ddd146104ed5780631f5e13341461052b57806323b872dd14610540578063313ce5671461056057600080fd5b8063156a0d0f14610484578063164e68de146104ab57806317442b70146104cb57600080fd5b80630d35b415116103495780630d35b415146103ed578063111ecdad1461041c57806313137d6514610449578063134d4f251461045c57600080fd5b806306fdde0314610370578063077f224a1461039b578063095ea7b3146103bd575b600080fd5b34801561037c57600080fd5b50610385610b71565b6040516103929190613011565b60405180910390f35b3480156103a757600080fd5b506103bb6103b6366004613124565b610c34565b005b3480156103c957600080fd5b506103dd6103d836600461319b565b610d4b565b6040519015158152602001610392565b3480156103f957600080fd5b5061040d6104083660046131df565b610d65565b60405161039293929190613213565b34801561042857600080fd5b50610431610e31565b6040516001600160a01b039091168152602001610392565b6103bb6104573660046132ff565b610e66565b34801561046857600080fd5b50610471600281565b60405161ffff9091168152602001610392565b34801561049057600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104b757600080fd5b506103bb6104c636600461339e565b610f26565b3480156104d757600080fd5b5060408051600181526002602082015201610392565b3480156104f957600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b604051908152602001610392565b34801561053757600080fd5b50610471600181565b34801561054c57600080fd5b506103dd61055b3660046133bb565b610fca565b34801561056c57600080fd5b5060405160068152602001610392565b34801561058857600080fd5b50610604610597366004613415565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff16815260209283015115159281019290925201610392565b34801561063157600080fd5b506103bb610640366004613430565b610ff0565b34801561065157600080fd5b506103dd61066036600461339e565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561068a57600080fd5b5061069e61069936600461345a565b61105d565b60405161039291906134ab565b3480156106b757600080fd5b506103bb6106c63660046134d4565b6110c4565b3480156106d757600080fd5b506000546001600160a01b0316610431565b3480156106f557600080fd5b5030610431565b34801561070857600080fd5b506103856107173660046134ef565b61114b565b34801561072857600080fd5b506103dd610737366004613430565b63ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b34801561076c57600080fd5b5061051d61077b366004613430565b611226565b34801561078c57600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b3480156107c057600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422005461051d565b3480156107f457600080fd5b506103bb610803366004613522565b611269565b34801561081457600080fd5b506103bb61082336600461339e565b61133d565b34801561083457600080fd5b5061051d61084336600461339e565b6113b1565b34801561085457600080fd5b506103bb6113d9565b34801561086957600080fd5b50610880610878366004613430565b600092915050565b6040516001600160401b039091168152602001610392565b3480156108a457600080fd5b506103dd6108b336600461355e565b6001600160a01b0381163014949350505050565b3480156108d357600080fd5b506103bb6108e236600461339e565b6113ed565b3480156108f357600080fd5b506103bb61090236600461339e565b611449565b34801561091357600080fd5b50610431611501565b34801561092857600080fd5b5061038561152a565b34801561093d57600080fd5b5061051d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561097157600080fd5b5060006103dd565b34801561098557600080fd5b506103dd61099436600461319b565b611569565b3480156109a557600080fd5b50610431611577565b3480156109ba57600080fd5b506103bb6109c9366004613608565b6115a0565b3480156109da57600080fd5b5061051d6109e9366004613415565b63ffffffff16600090815260008051602061409f833981519152602052604090205490565b348015610a1a57600080fd5b50610385610a29366004613649565b611721565b348015610a3a57600080fd5b5060008051602061407f8339815191525461ffff16610471565b6103bb610a62366004613608565b6118b7565b610a7a610a753660046136a9565b611a4e565b60405161039292919061370b565b348015610a9457600080fd5b506103bb610aa336600461339e565b611a81565b6103bb610ab63660046132ff565b611b07565b348015610ac757600080fd5b506103bb610ad636600461339e565b611b36565b348015610ae757600080fd5b5061051d610af636600461375d565b611baa565b348015610b0757600080fd5b5061047161271081565b348015610b1d57600080fd5b506103bb610b2c36600461339e565b611bf4565b348015610b3d57600080fd5b506103bb610b4c36600461339e565b611cae565b348015610b5d57600080fd5b506103dd610b6c36600461378b565b611cec565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061405f83398151915291610bb0906137a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc906137a7565b8015610c295780601f10610bfe57610100808354040283529160200191610c29565b820191906000526020600020905b815481529060010190602001808311610c0c57829003601f168201915b505050505091505090565b6000610c3e611d0a565b805490915060ff600160401b82041615906001600160401b0316600081158015610c655750825b90506000826001600160401b03166001148015610c815750303b155b905081158015610c8f575080155b15610cad5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610cd757845460ff60401b1916600160401b1785555b610ce2888888611d33565b610ceb86611d53565b600080546001600160a01b03191690558315610d4157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d59818585611d64565b60019150505b92915050565b60408051808201909152600080825260208201526060610d98604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610dee565b604080518082019091526000815260606020820152815260200190600190039081610dc65790505b509350600080610e13604089013560608a0135610e0e60208c018c613415565b611d71565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610eb6576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ed090610ecb908a613415565b611dc2565b14610f0e57610ee26020880188613415565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ead565b610f1d87878787878787611e0d565b50505050505050565b610f2e611f74565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f7357604051630d00db4d60e31b815260040160405180910390fd5b60008255610f82308483611fa6565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fbd91815260200190565b60405180910390a2505050565b600033610fd8858285612005565b610fe3858585611fa6565b60019150505b9392505050565b610ff8611f74565b63ffffffff8216600081815260008051602061409f833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b6040805180820190915260008082526020820152600061108d60408501356060860135610e0e6020880188613415565b91505060008061109d868461206c565b90925090506110ba6110b26020880188613415565b8383886121b1565b9695505050505050565b6110cc611f74565b61271061ffff821611156110f35760405163c6cc5d7f60e01b815260040160405180910390fd5b60008051602061407f833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061119f906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546111cb906137a7565b80156112185780601f106111ed57610100808354040283529160200191611218565b820191906000526020600020905b8154815290600101906020018083116111fb57829003601f168201915b505050505091505092915050565b60008061123284612292565b905061ffff81161561125e5761271061124f61ffff8316856137f1565b6112599190613808565b611261565b60005b949350505050565b611271611f74565b61271061ffff831611156112985760405163c6cc5d7f60e01b815260040160405180910390fd5b600060008051602061407f83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a150505050565b611345611f74565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d44141979060200161113f565b6001600160a01b0316600090815260008051602061405f833981519152602052604090205490565b6113e1611f74565b6113eb6000612311565b565b6113f5611f74565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b611451611f74565b6001600160a01b03811660009081526001602052604090205460ff166114ab5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ead565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e56565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061405f83398151915291610bb0906137a7565b600033610d59818585611fa6565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e56565b6115a8611f74565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156116ef5761160e8484838181106115e9576115e961382a565b90506020028101906115fb9190613840565b611609906040810190613860565b612382565b8383828181106116205761162061382a565b90506020028101906116329190613840565b611640906040810190613860565b8360008787868181106116555761165561382a565b90506020028101906116679190613840565b611675906020810190613415565b63ffffffff1663ffffffff16815260200190815260200160002060008787868181106116a3576116a361382a565b90506020028101906116b59190613840565b6116c69060408101906020016134d4565b61ffff1681526020810191909152604001600020916116e69190836138f6565b506001016115cc565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67483836040516110509291906139de565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611774906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117a0906137a7565b80156117ed5780601f106117c2576101008083540402835291602001916117ed565b820191906000526020600020905b8154815290600101906020018083116117d057829003601f168201915b50505050509050805160000361183e5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611261945050505050565b60008490036118505791506112619050565b6002841061189a576118628585612382565b806118708560028189613ac2565b60405160200161188293929190613aec565b60405160208183030381529060405292505050611261565b8484604051639a6d49cd60e01b8152600401610ead929190613b14565b60005b818110156119cd57368383838181106118d5576118d561382a565b90506020028101906118e79190613b28565b90506119276118f96020830183613415565b602083013563ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b61193157506119c5565b3063d045a0dc60c08301358360a0810135611950610100830183613860565b611961610100890160e08a0161339e565b61196f6101208a018a613860565b6040518963ffffffff1660e01b81526004016119919796959493929190613b54565b6000604051808303818588803b1580156119aa57600080fd5b505af11580156119be573d6000803e3d6000fd5b5050505050505b6001016118ba565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a349190810190613bda565b604051638351eea760e01b8152600401610ead9190613011565b611a56612f7a565b6040805180820190915260008082526020820152611a758585856123c4565b91509150935093915050565b611a89611f74565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b158015611aec57600080fd5b505af1158015611b00573d6000803e3d6000fd5b5050505050565b333014611b275760405163029a949d60e31b815260040160405180910390fd5b610f1d87878787878787610f0e565b611b3e611f74565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c24277609060200161113f565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611bfc611f74565b6001600160a01b03811660009081526001602052604090205460ff1615611c5b5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ead565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016114f6565b611cb6611f74565b6001600160a01b038116611ce057604051631e4fbdf760e01b815260006004820152602401610ead565b611ce981612311565b50565b600060208201803590611d03906109e99085613415565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d5f565b611d3b6124bf565b611d4583836124e4565b611d4e816124fa565b505050565b611d5b6124bf565b611ce98161251b565b611d4e8383836001612523565b82600080611d7f8484611226565b9050611d8c81870361260a565b915084821015611db9576040516371c4efed60e01b81526004810183905260248101869052604401610ead565b50935093915050565b63ffffffff8116600090815260008051602061409f8339815191526020819052604082205480610fe95760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ead565b6000611e1f611e1c8787612641565b90565b90506000611e4b82611e39611e348a8a612659565b61267c565b611e4660208d018d613415565b6126b1565b90506028861115611f12576000611e88611e6b60608c0160408d01613c47565b611e7860208d018d613415565b84611e838c8c6126d9565b612724565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb5901290611ede9086908d906000908790600401613c64565b600060405180830381600087803b158015611ef857600080fd5b505af1158015611f0c573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611f4b60208d018d613415565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b33611f7d611501565b6001600160a01b0316146113eb5760405163118cdaa760e01b8152336004820152602401610ead565b6001600160a01b038316611fd057604051634b637e8f60e11b815260006004820152602401610ead565b6001600160a01b038216611ffa5760405163ec442f0560e01b815260006004820152602401610ead565b611d4e838383612756565b60006120118484611baa565b9050600019811015612066578181101561205757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ead565b61206684848484036000612523565b50505050565b60608060006120c98560200135612082866127e4565b61208f60a0890189613860565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283e92505050565b90935090506000816120dc5760016120df565b60025b90506120ff6120f16020880188613415565b82610a2960808a018a613860565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156121a65760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906121639089908990600401613c95565b602060405180830381865afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a49190613cba565b505b505050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161221489611dc2565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612249929190613cd7565b6040805180830381865afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190613d80565b95945050505050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905260008051602061407f8339815191529161230957815461ffff16611261565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006123916002828486613ac2565b61239a91613d9c565b60f01c905060038114611d4e578282604051639a6d49cd60e01b8152600401610ead929190613b14565b6123cc612f7a565b604080518082019091526000808252602082015260008061240333604089013560608a01356123fe60208c018c613415565b6128b8565b91509150600080612414898461206c565b909250905061244061242960208b018b613415565b838361243a368d90038d018d613dcc565b8b6129ec565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061248e908d018d613415565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6124c7612af7565b6113eb57604051631afcd79f60e31b815260040160405180910390fd5b6124ec6124bf565b6124f68282612b11565b5050565b6125026124bf565b61250b81612b62565b612513612b73565b611ce9612b73565b611cb66124bf565b60008051602061405f8339815191526001600160a01b03851661255c5760405163e602df0560e01b815260006004820152602401610ead565b6001600160a01b03841661258657604051634a1406b160e11b815260006004820152602401610ead565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611b0057836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516125fb91815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006126378184613808565b610d5f91906137f1565b60006126506020828486613ac2565b610fe991613dfe565b6000612669602860208486613ac2565b61267291613e1c565b60c01c9392505050565b6000610d5f7f00000000000000000000000000000000000000000000000000000000000000006001600160401b0384166137f1565b60006001600160a01b0384166126c75761dead93505b6126d18484612b7b565b509092915050565b60606126e88260288186613ac2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161273d9493929190613e4a565b6040516020818303038152906040529050949350505050565b612761838383612bb1565b6002805490600061277183613e99565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846127b8886113b1565b6127c1886113b1565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128117f000000000000000000000000000000000000000000000000000000000000000084613808565b90506001600160401b03811115610d5f5760405163e2ce941360e01b815260048101829052602401610ead565b805160609015158061288757848460405160200161287392919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526128ae565b8484338560405160200161289e9493929190613eb2565b6040516020818303038152906040525b9150935093915050565b6001600160a01b038416600090815260016020526040812054819060ff166128ea576128e5858585611d71565b6128f4565b6128f48585612cef565b9092509050818111156129645760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ead565b60006129708284613ef5565b905080156129d8576000546001600160a01b03166129c0577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422008054820181556129ba883084611fa6565b506129d8565b6000546129d89088906001600160a01b031683611fa6565b6129e28783612d2f565b5094509492505050565b6129f4612f7a565b6000612a038460000151612d65565b602085015190915015612a1d57612a1d8460200151612d8d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612a6d8c611dc2565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612aa9929190613cd7565b60806040518083038185885af1158015612ac7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aec9190613f08565b979650505050505050565b6000612b01611d0a565b54600160401b900460ff16919050565b612b196124bf565b60008051602061405f8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03612b538482613f6f565b50600481016120668382613f6f565b612b6a6124bf565b61250b81612e6f565b6113eb6124bf565b6001600160a01b038216612ba55760405163ec442f0560e01b815260006004820152602401610ead565b6124f660008383612756565b60008051602061405f8339815191526001600160a01b038416612bed5781816002016000828254612be2919061402e565b90915550612c5f9050565b6001600160a01b03841660009081526020829052604090205482811015612c405760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ead565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612c7d576002810180548390039055612c9c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ce191815260200190565b60405180910390a350505050565b816000612cfb8261260a565b905082811015612d28576040516371c4efed60e01b81526004810182905260248101849052604401610ead565b9250929050565b6001600160a01b038216612d5957604051634b637e8f60e11b815260006004820152602401610ead565b6124f682600083612756565b6000813414612d89576040516304fb820960e51b8152346004820152602401610ead565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e119190614041565b90506001600160a01b038116612e3a576040516329b99a9560e11b815260040160405180910390fd5b6124f66001600160a01b038216337f000000000000000000000000000000000000000000000000000000000000000085612e80565b612e776124bf565b611ce981612eda565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612066908590612f09565b612ee26124bf565b6001600160a01b038116611a8957604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180612f2c576040513d6000823e3d81fd5b50506000513d91508115612f44578060011415612f51565b6001600160a01b0384163b155b1561206657604051635274afe760e01b81526001600160a01b0385166004820152602401610ead565b60405180606001604052806000801916815260200160006001600160401b03168152602001612fbc604051806040016040528060008152602001600081525090565b905290565b60005b83811015612fdc578181015183820152602001612fc4565b50506000910152565b60008151808452612ffd816020860160208601612fc1565b601f01601f19169290920160200192915050565b602081526000610fe96020830184612fe5565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561305c5761305c613024565b60405290565b604051601f8201601f191681016001600160401b038111828210171561308a5761308a613024565b604052919050565b60006001600160401b038211156130ab576130ab613024565b50601f01601f191660200190565b600082601f8301126130ca57600080fd5b81356130dd6130d882613092565b613062565b8181528460208386010111156130f257600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611ce957600080fd5b60008060006060848603121561313957600080fd5b83356001600160401b038082111561315057600080fd5b61315c878388016130b9565b9450602086013591508082111561317257600080fd5b5061317f868287016130b9565b92505060408401356131908161310f565b809150509250925092565b600080604083850312156131ae57600080fd5b82356131b98161310f565b946020939093013593505050565b600060e082840312156131d957600080fd5b50919050565b6000602082840312156131f157600080fd5b81356001600160401b0381111561320757600080fd5b611261848285016131c7565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561328e5788870360bf1901855281518051885283015183880187905261327b87890182612fe5565b975050938201939082019060010161324f565b50508751606088015250505060208501516080850152509050611261565b6000606082840312156131d957600080fd5b60008083601f8401126132d057600080fd5b5081356001600160401b038111156132e757600080fd5b602083019150836020828501011115612d2857600080fd5b600080600080600080600060e0888a03121561331a57600080fd5b61332489896132ac565b96506060880135955060808801356001600160401b038082111561334757600080fd5b6133538b838c016132be565b909750955060a08a013591506133688261310f565b90935060c0890135908082111561337e57600080fd5b5061338b8a828b016132be565b989b979a50959850939692959293505050565b6000602082840312156133b057600080fd5b8135610fe98161310f565b6000806000606084860312156133d057600080fd5b83356133db8161310f565b925060208401356133eb8161310f565b929592945050506040919091013590565b803563ffffffff8116811461341057600080fd5b919050565b60006020828403121561342757600080fd5b610fe9826133fc565b6000806040838503121561344357600080fd5b6131b9836133fc565b8015158114611ce957600080fd5b6000806040838503121561346d57600080fd5b82356001600160401b0381111561348357600080fd5b61348f858286016131c7565b92505060208301356134a08161344c565b809150509250929050565b815181526020808301519082015260408101610d5f565b803561ffff8116811461341057600080fd5b6000602082840312156134e657600080fd5b610fe9826134c2565b6000806040838503121561350257600080fd5b61350b836133fc565b9150613519602084016134c2565b90509250929050565b60008060006060848603121561353757600080fd5b613540846133fc565b925061354e602085016134c2565b915060408401356131908161344c565b60008060008060a0858703121561357457600080fd5b61357e86866132ac565b935060608501356001600160401b0381111561359957600080fd5b6135a5878288016132be565b90945092505060808501356135b98161310f565b939692955090935050565b60008083601f8401126135d657600080fd5b5081356001600160401b038111156135ed57600080fd5b6020830191508360208260051b8501011115612d2857600080fd5b6000806020838503121561361b57600080fd5b82356001600160401b0381111561363157600080fd5b61363d858286016135c4565b90969095509350505050565b6000806000806060858703121561365f57600080fd5b613668856133fc565b9350613676602086016134c2565b925060408501356001600160401b0381111561369157600080fd5b61369d878288016132be565b95989497509550505050565b600080600083850360808112156136bf57600080fd5b84356001600160401b038111156136d557600080fd5b6136e1878288016131c7565b9450506040601f19820112156136f657600080fd5b5060208401915060608401356131908161310f565b600060c082019050835182526001600160401b0360208501511660208301526040840151613746604084018280518252602090810151910152565b5082516080830152602083015160a0830152610fe9565b6000806040838503121561377057600080fd5b823561377b8161310f565b915060208301356134a08161310f565b60006060828403121561379d57600080fd5b610fe983836132ac565b600181811c908216806137bb57607f821691505b6020821081036131d957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d5f57610d5f6137db565b60008261382557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e1983360301811261385657600080fd5b9190910192915050565b6000808335601e1984360301811261387757600080fd5b8301803591506001600160401b0382111561389157600080fd5b602001915036819003821315612d2857600080fd5b601f821115611d4e576000816000526020600020601f850160051c810160208610156138cf5750805b601f850160051c820191505b818110156138ee578281556001016138db565b505050505050565b6001600160401b0383111561390d5761390d613024565b6139218361391b83546137a7565b836138a6565b6000601f841160018114613955576000851561393d5750838201355b600019600387901b1c1916600186901b178355611b00565b600083815260209020601f19861690835b828110156139865786850135825560209485019460019092019101613966565b50868210156139a35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613ab457878303603f190184528135368b9003605e19018112613a2357600080fd5b8a01606063ffffffff613a35836133fc565b16855261ffff613a468984016134c2565b168886015286820135601e19833603018112613a6157600080fd5b9091018781019190356001600160401b03811115613a7e57600080fd5b803603831315613a8d57600080fd5b8188870152613a9f82870182856139b5565b968901969550505091860191506001016139fd565b509098975050505050505050565b60008085851115613ad257600080fd5b83861115613adf57600080fd5b5050820193919092039150565b60008451613afe818460208901612fc1565b8201838582376000930192835250909392505050565b6020815260006112616020830184866139b5565b6000823561013e1983360301811261385657600080fd5b6001600160401b0381168114611ce957600080fd5b63ffffffff613b62896133fc565b1681526020880135602082015260006040890135613b7f81613b3f565b6001600160401b03811660408401525087606083015260e06080830152613baa60e0830187896139b5565b6001600160a01b03861660a084015282810360c0840152613bcc8185876139b5565b9a9950505050505050505050565b600060208284031215613bec57600080fd5b81516001600160401b03811115613c0257600080fd5b8201601f81018413613c1357600080fd5b8051613c216130d882613092565b818152856020838501011115613c3657600080fd5b612289826020830160208601612fc1565b600060208284031215613c5957600080fd5b8135610fe981613b3f565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110ba6080830184612fe5565b604081526000613ca86040830185612fe5565b82810360208401526122898185612fe5565b600060208284031215613ccc57600080fd5b8151610fe98161344c565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613d0d60e0840182612fe5565b90506060850151603f198483030160a0850152613d2a8282612fe5565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613d6257600080fd5b613d6a61303a565b9050815181526020820151602082015292915050565b600060408284031215613d9257600080fd5b610fe98383613d50565b6001600160f01b03198135818116916002851015613dc45780818660020360031b1b83161692505b505092915050565b600060408284031215613dde57600080fd5b613de661303a565b82358152602083013560208201528091505092915050565b80356020831015610d5f57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613dc45760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613e8981602c850160208701612fc1565b91909101602c0195945050505050565b600060018201613eab57613eab6137db565b5060010190565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613ee5816048850160208701612fc1565b9190910160480195945050505050565b81810381811115610d5f57610d5f6137db565b600060808284031215613f1a57600080fd5b604051606081018181106001600160401b0382111715613f3c57613f3c613024565b604052825181526020830151613f5181613b3f565b6020820152613f638460408501613d50565b60408201529392505050565b81516001600160401b03811115613f8857613f88613024565b613f9c81613f9684546137a7565b846138a6565b602080601f831160018114613fd15760008415613fb95750858301515b600019600386901b1c1916600185901b1785556138ee565b600085815260208120601f198616915b8281101561400057888601518255948401946001909101908401613fe1565b508582101561401e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610d5f57610d5f6137db565b60006020828403121561405357600080fd5b8151610fe98161310f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a164736f6c634300081600330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode
0x60806040526004361061036b5760003560e01c806370a08231116101c6578063bb0b6a53116100f7578063d424388511610095578063e43252d71161006f578063e43252d714610b11578063f2fde38b14610b31578063fc0c546a146106e9578063ff7bd03d14610b5157600080fd5b8063d424388514610abb578063dd62ed3e14610adb578063e1a4521814610afb57600080fd5b8063bd815db0116100d1578063bd815db014610a54578063c7c7f5b314610a67578063ca5eb5e114610a88578063d045a0dc14610aa857600080fd5b8063bb0b6a53146109ce578063bc70b35414610a0e578063bcae25a414610a2e57600080fd5b80638da5cb5b116101645780639f68b9641161013e5780639f68b96414610965578063a9059cbb14610979578063b731ea0a14610999578063b98bd070146109ae57600080fd5b80638da5cb5b1461090757806395d89b411461091c578063963efcaa1461093157600080fd5b806382413eac116101a057806382413eac14610898578063857749b0146105605780638705fcd4146108c75780638ab1d681146108e757600080fd5b806370a0823114610828578063715018a6146108485780637d25a05e1461085d57600080fd5b80633194c180116102a05780635535d4611161023e5780635e280f11116102185780635e280f111461078057806360b71d4e146107b45780636db7bcdb146107e85780636fc1b31e1461080857600080fd5b80635535d461146106fc5780635a0dfe4d1461071c5780635bf9c2261461076057600080fd5b80633b6f743b1161027a5780633b6f743b1461067e5780634488b652146106ab5780634e7ceacb146106cb57806352ae2879146106e957600080fd5b80633194c1801461057c5780633400288b146106255780633af32abf1461064557600080fd5b8063156a0d0f1161030d57806318160ddd116102e757806318160ddd146104ed5780631f5e13341461052b57806323b872dd14610540578063313ce5671461056057600080fd5b8063156a0d0f14610484578063164e68de146104ab57806317442b70146104cb57600080fd5b80630d35b415116103495780630d35b415146103ed578063111ecdad1461041c57806313137d6514610449578063134d4f251461045c57600080fd5b806306fdde0314610370578063077f224a1461039b578063095ea7b3146103bd575b600080fd5b34801561037c57600080fd5b50610385610b71565b6040516103929190613011565b60405180910390f35b3480156103a757600080fd5b506103bb6103b6366004613124565b610c34565b005b3480156103c957600080fd5b506103dd6103d836600461319b565b610d4b565b6040519015158152602001610392565b3480156103f957600080fd5b5061040d6104083660046131df565b610d65565b60405161039293929190613213565b34801561042857600080fd5b50610431610e31565b6040516001600160a01b039091168152602001610392565b6103bb6104573660046132ff565b610e66565b34801561046857600080fd5b50610471600281565b60405161ffff9091168152602001610392565b34801561049057600080fd5b506040805162b9270b60e21b81526001602082015201610392565b3480156104b757600080fd5b506103bb6104c636600461339e565b610f26565b3480156104d757600080fd5b5060408051600181526002602082015201610392565b3480156104f957600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b604051908152602001610392565b34801561053757600080fd5b50610471600181565b34801561054c57600080fd5b506103dd61055b3660046133bb565b610fca565b34801561056c57600080fd5b5060405160068152602001610392565b34801561058857600080fd5b50610604610597366004613415565b6040805180820182526000808252602091820181905263ffffffff9390931683527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80181529181902081518083019092525461ffff8116825262010000900460ff1615159181019190915290565b60408051825161ffff16815260209283015115159281019290925201610392565b34801561063157600080fd5b506103bb610640366004613430565b610ff0565b34801561065157600080fd5b506103dd61066036600461339e565b6001600160a01b031660009081526001602052604090205460ff1690565b34801561068a57600080fd5b5061069e61069936600461345a565b61105d565b60405161039291906134ab565b3480156106b757600080fd5b506103bb6106c63660046134d4565b6110c4565b3480156106d757600080fd5b506000546001600160a01b0316610431565b3480156106f557600080fd5b5030610431565b34801561070857600080fd5b506103856107173660046134ef565b61114b565b34801561072857600080fd5b506103dd610737366004613430565b63ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b34801561076c57600080fd5b5061051d61077b366004613430565b611226565b34801561078c57600080fd5b506104317f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b3480156107c057600080fd5b507f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422005461051d565b3480156107f457600080fd5b506103bb610803366004613522565b611269565b34801561081457600080fd5b506103bb61082336600461339e565b61133d565b34801561083457600080fd5b5061051d61084336600461339e565b6113b1565b34801561085457600080fd5b506103bb6113d9565b34801561086957600080fd5b50610880610878366004613430565b600092915050565b6040516001600160401b039091168152602001610392565b3480156108a457600080fd5b506103dd6108b336600461355e565b6001600160a01b0381163014949350505050565b3480156108d357600080fd5b506103bb6108e236600461339e565b6113ed565b3480156108f357600080fd5b506103bb61090236600461339e565b611449565b34801561091357600080fd5b50610431611501565b34801561092857600080fd5b5061038561152a565b34801561093d57600080fd5b5061051d7f000000000000000000000000000000000000000000000000000000000000000181565b34801561097157600080fd5b5060006103dd565b34801561098557600080fd5b506103dd61099436600461319b565b611569565b3480156109a557600080fd5b50610431611577565b3480156109ba57600080fd5b506103bb6109c9366004613608565b6115a0565b3480156109da57600080fd5b5061051d6109e9366004613415565b63ffffffff16600090815260008051602061409f833981519152602052604090205490565b348015610a1a57600080fd5b50610385610a29366004613649565b611721565b348015610a3a57600080fd5b5060008051602061407f8339815191525461ffff16610471565b6103bb610a62366004613608565b6118b7565b610a7a610a753660046136a9565b611a4e565b60405161039292919061370b565b348015610a9457600080fd5b506103bb610aa336600461339e565b611a81565b6103bb610ab63660046132ff565b611b07565b348015610ac757600080fd5b506103bb610ad636600461339e565b611b36565b348015610ae757600080fd5b5061051d610af636600461375d565b611baa565b348015610b0757600080fd5b5061047161271081565b348015610b1d57600080fd5b506103bb610b2c36600461339e565b611bf4565b348015610b3d57600080fd5b506103bb610b4c36600461339e565b611cae565b348015610b5d57600080fd5b506103dd610b6c36600461378b565b611cec565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061405f83398151915291610bb0906137a7565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdc906137a7565b8015610c295780601f10610bfe57610100808354040283529160200191610c29565b820191906000526020600020905b815481529060010190602001808311610c0c57829003601f168201915b505050505091505090565b6000610c3e611d0a565b805490915060ff600160401b82041615906001600160401b0316600081158015610c655750825b90506000826001600160401b03166001148015610c815750303b155b905081158015610c8f575080155b15610cad5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610cd757845460ff60401b1916600160401b1785555b610ce2888888611d33565b610ceb86611d53565b600080546001600160a01b03191690558315610d4157845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b600033610d59818585611d64565b60019150505b92915050565b60408051808201909152600080825260208201526060610d98604051806040016040528060008152602001600081525090565b6040805180820182526000808252600019602080840182905284518381529081019094529195509182610dee565b604080518082019091526000815260606020820152815260200190600190039081610dc65790505b509350600080610e13604089013560608a0135610e0e60208c018c613415565b611d71565b60408051808201909152918252602082015296989597505050505050565b6000807f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c005b546001600160a01b031692915050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610eb6576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ed090610ecb908a613415565b611dc2565b14610f0e57610ee26020880188613415565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610ead565b610f1d87878787878787611e0d565b50505050505050565b610f2e611f74565b7f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b34220080546000819003610f7357604051630d00db4d60e31b815260040160405180910390fd5b60008255610f82308483611fa6565b826001600160a01b03167f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f82604051610fbd91815260200190565b60405180910390a2505050565b600033610fd8858285612005565b610fe3858585611fa6565b60019150505b9392505050565b610ff8611f74565b63ffffffff8216600081815260008051602061409f833981519152602081815260409283902085905582519384528301849052917f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b91015b60405180910390a1505050565b6040805180820190915260008082526020820152600061108d60408501356060860135610e0e6020880188613415565b91505060008061109d868461206c565b90925090506110ba6110b26020880188613415565b8383886121b1565b9695505050505050565b6110cc611f74565b61271061ffff821611156110f35760405163c6cc5d7f60e01b815260040160405180910390fd5b60008051602061407f833981519152805461ffff191661ffff831690811782556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a15050565b63ffffffff821660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff861685529091529091208054606092919061119f906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546111cb906137a7565b80156112185780601f106111ed57610100808354040283529160200191611218565b820191906000526020600020905b8154815290600101906020018083116111fb57829003601f168201915b505050505091505092915050565b60008061123284612292565b905061ffff81161561125e5761271061124f61ffff8316856137f1565b6112599190613808565b611261565b60005b949350505050565b611271611f74565b61271061ffff831611156112985760405163c6cc5d7f60e01b815260040160405180910390fd5b600060008051602061407f83398151915260408051808201825261ffff868116808352861515602080850182815263ffffffff8c16600081815260018a0184528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201529091507f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a150505050565b611345611f74565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c0080546001600160a01b0319166001600160a01b03831690811782556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d44141979060200161113f565b6001600160a01b0316600090815260008051602061405f833981519152602052604090205490565b6113e1611f74565b6113eb6000612311565b565b6113f5611f74565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f0cc4d0c9af0c184a6ba4203a2d8f4a6843759ea43f751b50f516f6fb4241d9df9060200160405180910390a150565b611451611f74565b6001600160a01b03811660009081526001602052604090205460ff166114ab5760405162461bcd60e51b815260206004820152600f60248201526e139bdd081dda1a5d195b1a5cdd1959608a1b6044820152606401610ead565b6001600160a01b0381166000818152600160209081526040808320805460ff19169055519182527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91015b60405180910390a250565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300610e56565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061405f83398151915291610bb0906137a7565b600033610d59818585611fa6565b6000807fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b600610e56565b6115a8611f74565b7f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea000060005b828110156116ef5761160e8484838181106115e9576115e961382a565b90506020028101906115fb9190613840565b611609906040810190613860565b612382565b8383828181106116205761162061382a565b90506020028101906116329190613840565b611640906040810190613860565b8360008787868181106116555761165561382a565b90506020028101906116679190613840565b611675906020810190613415565b63ffffffff1663ffffffff16815260200190815260200160002060008787868181106116a3576116a361382a565b90506020028101906116b59190613840565b6116c69060408101906020016134d4565b61ffff1681526020810191909152604001600020916116e69190836138f6565b506001016115cc565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67483836040516110509291906139de565b63ffffffff841660009081527f8d2bda5d9f6ffb5796910376005392955773acee5548d0fcdb10e7c264ea00006020818152604080842061ffff88168552909152822080546060939190611774906137a7565b80601f01602080910402602001604051908101604052809291908181526020018280546117a0906137a7565b80156117ed5780601f106117c2576101008083540402835291602001916117ed565b820191906000526020600020905b8154815290600101906020018083116117d057829003601f168201915b50505050509050805160000361183e5784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611261945050505050565b60008490036118505791506112619050565b6002841061189a576118628585612382565b806118708560028189613ac2565b60405160200161188293929190613aec565b60405160208183030381529060405292505050611261565b8484604051639a6d49cd60e01b8152600401610ead929190613b14565b60005b818110156119cd57368383838181106118d5576118d561382a565b90506020028101906118e79190613b28565b90506119276118f96020830183613415565b602083013563ffffffff91909116600090815260008051602061409f83398151915260205260409020541490565b61193157506119c5565b3063d045a0dc60c08301358360a0810135611950610100830183613860565b611961610100890160e08a0161339e565b61196f6101208a018a613860565b6040518963ffffffff1660e01b81526004016119919796959493929190613b54565b6000604051808303818588803b1580156119aa57600080fd5b505af11580156119be573d6000803e3d6000fd5b5050505050505b6001016118ba565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a349190810190613bda565b604051638351eea760e01b8152600401610ead9190613011565b611a56612f7a565b6040805180820190915260008082526020820152611a758585856123c4565b91509150935093915050565b611a89611f74565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e190602401600060405180830381600087803b158015611aec57600080fd5b505af1158015611b00573d6000803e3d6000fd5b5050505050565b333014611b275760405163029a949d60e31b815260040160405180910390fd5b610f1d87878787878787610f0e565b611b3e611f74565b7fefb041d771d6daaa55702fff6eb740d63ba559a75d2d1d3e151c78ff2480b60080546001600160a01b0319166001600160a01b03831690811782556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c24277609060200161113f565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611bfc611f74565b6001600160a01b03811660009081526001602052604090205460ff1615611c5b5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481dda1a5d195b1a5cdd1959606a1b6044820152606401610ead565b6001600160a01b038116600081815260016020818152604092839020805460ff19168317905591519081527ff93f9a76c1bf3444d22400a00cb9fe990e6abe9dbb333fda48859cfee864543d91016114f6565b611cb6611f74565b6001600160a01b038116611ce057604051631e4fbdf760e01b815260006004820152602401610ead565b611ce981612311565b50565b600060208201803590611d03906109e99085613415565b1492915050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d5f565b611d3b6124bf565b611d4583836124e4565b611d4e816124fa565b505050565b611d5b6124bf565b611ce98161251b565b611d4e8383836001612523565b82600080611d7f8484611226565b9050611d8c81870361260a565b915084821015611db9576040516371c4efed60e01b81526004810183905260248101869052604401610ead565b50935093915050565b63ffffffff8116600090815260008051602061409f8339815191526020819052604082205480610fe95760405163f6ff4fb760e01b815263ffffffff85166004820152602401610ead565b6000611e1f611e1c8787612641565b90565b90506000611e4b82611e39611e348a8a612659565b61267c565b611e4660208d018d613415565b6126b1565b90506028861115611f12576000611e88611e6b60608c0160408d01613c47565b611e7860208d018d613415565b84611e838c8c6126d9565b612724565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb5901290611ede9086908d906000908790600401613c64565b600060405180830381600087803b158015611ef857600080fd5b505af1158015611f0c573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c611f4b60208d018d613415565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b33611f7d611501565b6001600160a01b0316146113eb5760405163118cdaa760e01b8152336004820152602401610ead565b6001600160a01b038316611fd057604051634b637e8f60e11b815260006004820152602401610ead565b6001600160a01b038216611ffa5760405163ec442f0560e01b815260006004820152602401610ead565b611d4e838383612756565b60006120118484611baa565b9050600019811015612066578181101561205757604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610ead565b61206684848484036000612523565b50505050565b60608060006120c98560200135612082866127e4565b61208f60a0890189613860565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283e92505050565b90935090506000816120dc5760016120df565b60025b90506120ff6120f16020880188613415565b82610a2960808a018a613860565b7f41db8a78b0206aba5c54bcbfc2bda0d84082a84eb88e680379a57b9e9f653c008054919450906001600160a01b031680156121a65760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906121639089908990600401613c95565b602060405180830381865afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a49190613cba565b505b505050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff16815260200161221489611dc2565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401612249929190613cd7565b6040805180830381865afa158015612265573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122899190613d80565b95945050505050565b63ffffffff811660009081527f0cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de8016020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905260008051602061407f8339815191529161230957815461ffff16611261565b519392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60006123916002828486613ac2565b61239a91613d9c565b60f01c905060038114611d4e578282604051639a6d49cd60e01b8152600401610ead929190613b14565b6123cc612f7a565b604080518082019091526000808252602082015260008061240333604089013560608a01356123fe60208c018c613415565b6128b8565b91509150600080612414898461206c565b909250905061244061242960208b018b613415565b838361243a368d90038d018d613dcc565b8b6129ec565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a9061248e908d018d613415565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6124c7612af7565b6113eb57604051631afcd79f60e31b815260040160405180910390fd5b6124ec6124bf565b6124f68282612b11565b5050565b6125026124bf565b61250b81612b62565b612513612b73565b611ce9612b73565b611cb66124bf565b60008051602061405f8339815191526001600160a01b03851661255c5760405163e602df0560e01b815260006004820152602401610ead565b6001600160a01b03841661258657604051634a1406b160e11b815260006004820152602401610ead565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115611b0057836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516125fb91815260200190565b60405180910390a35050505050565b60007f00000000000000000000000000000000000000000000000000000000000000016126378184613808565b610d5f91906137f1565b60006126506020828486613ac2565b610fe991613dfe565b6000612669602860208486613ac2565b61267291613e1c565b60c01c9392505050565b6000610d5f7f00000000000000000000000000000000000000000000000000000000000000016001600160401b0384166137f1565b60006001600160a01b0384166126c75761dead93505b6126d18484612b7b565b509092915050565b60606126e88260288186613ac2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b60608484848460405160200161273d9493929190613e4a565b6040516020818303038152906040529050949350505050565b612761838383612bb1565b6002805490600061277183613e99565b9190505550600254826001600160a01b0316846001600160a01b03167f6d16356255ebed8e5918262476684aaa5f8054befd93154494221a6026157aa5846127b8886113b1565b6127c1886113b1565b6040805193845260208401929092529082015260600160405180910390a4505050565b6000806128117f000000000000000000000000000000000000000000000000000000000000000184613808565b90506001600160401b03811115610d5f5760405163e2ce941360e01b815260048101829052602401610ead565b805160609015158061288757848460405160200161287392919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526128ae565b8484338560405160200161289e9493929190613eb2565b6040516020818303038152906040525b9150935093915050565b6001600160a01b038416600090815260016020526040812054819060ff166128ea576128e5858585611d71565b6128f4565b6128f48585612cef565b9092509050818111156129645760405162461bcd60e51b815260206004820152603260248201527f416d6f756e742072656365697665642063616e6e6f74206265206772656174656044820152711c881d1a185b88185b5bdd5b9d081cd95b9d60721b6064820152608401610ead565b60006129708284613ef5565b905080156129d8576000546001600160a01b03166129c0577f68f1d0d99488c60d21eadee2cca13b58661d56fbcb4e4464d6fc8def1b3422008054820181556129ba883084611fa6565b506129d8565b6000546129d89088906001600160a01b031683611fa6565b6129e28783612d2f565b5094509492505050565b6129f4612f7a565b6000612a038460000151612d65565b602085015190915015612a1d57612a1d8460200151612d8d565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001612a6d8c611dc2565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401612aa9929190613cd7565b60806040518083038185885af1158015612ac7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612aec9190613f08565b979650505050505050565b6000612b01611d0a565b54600160401b900460ff16919050565b612b196124bf565b60008051602061405f8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03612b538482613f6f565b50600481016120668382613f6f565b612b6a6124bf565b61250b81612e6f565b6113eb6124bf565b6001600160a01b038216612ba55760405163ec442f0560e01b815260006004820152602401610ead565b6124f660008383612756565b60008051602061405f8339815191526001600160a01b038416612bed5781816002016000828254612be2919061402e565b90915550612c5f9050565b6001600160a01b03841660009081526020829052604090205482811015612c405760405163391434e360e21b81526001600160a01b03861660048201526024810182905260448101849052606401610ead565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316612c7d576002810180548390039055612c9c565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ce191815260200190565b60405180910390a350505050565b816000612cfb8261260a565b905082811015612d28576040516371c4efed60e01b81526004810182905260248101849052604401610ead565b9250929050565b6001600160a01b038216612d5957604051634b637e8f60e11b815260006004820152602401610ead565b6124f682600083612756565b6000813414612d89576040516304fb820960e51b8152346004820152602401610ead565b5090565b60007f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e119190614041565b90506001600160a01b038116612e3a576040516329b99a9560e11b815260040160405180910390fd5b6124f66001600160a01b038216337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b85612e80565b612e776124bf565b611ce981612eda565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052612066908590612f09565b612ee26124bf565b6001600160a01b038116611a8957604051632d618d8160e21b815260040160405180910390fd5b600080602060008451602086016000885af180612f2c576040513d6000823e3d81fd5b50506000513d91508115612f44578060011415612f51565b6001600160a01b0384163b155b1561206657604051635274afe760e01b81526001600160a01b0385166004820152602401610ead565b60405180606001604052806000801916815260200160006001600160401b03168152602001612fbc604051806040016040528060008152602001600081525090565b905290565b60005b83811015612fdc578181015183820152602001612fc4565b50506000910152565b60008151808452612ffd816020860160208601612fc1565b601f01601f19169290920160200192915050565b602081526000610fe96020830184612fe5565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561305c5761305c613024565b60405290565b604051601f8201601f191681016001600160401b038111828210171561308a5761308a613024565b604052919050565b60006001600160401b038211156130ab576130ab613024565b50601f01601f191660200190565b600082601f8301126130ca57600080fd5b81356130dd6130d882613092565b613062565b8181528460208386010111156130f257600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114611ce957600080fd5b60008060006060848603121561313957600080fd5b83356001600160401b038082111561315057600080fd5b61315c878388016130b9565b9450602086013591508082111561317257600080fd5b5061317f868287016130b9565b92505060408401356131908161310f565b809150509250925092565b600080604083850312156131ae57600080fd5b82356131b98161310f565b946020939093013593505050565b600060e082840312156131d957600080fd5b50919050565b6000602082840312156131f157600080fd5b81356001600160401b0381111561320757600080fd5b611261848285016131c7565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b8381101561328e5788870360bf1901855281518051885283015183880187905261327b87890182612fe5565b975050938201939082019060010161324f565b50508751606088015250505060208501516080850152509050611261565b6000606082840312156131d957600080fd5b60008083601f8401126132d057600080fd5b5081356001600160401b038111156132e757600080fd5b602083019150836020828501011115612d2857600080fd5b600080600080600080600060e0888a03121561331a57600080fd5b61332489896132ac565b96506060880135955060808801356001600160401b038082111561334757600080fd5b6133538b838c016132be565b909750955060a08a013591506133688261310f565b90935060c0890135908082111561337e57600080fd5b5061338b8a828b016132be565b989b979a50959850939692959293505050565b6000602082840312156133b057600080fd5b8135610fe98161310f565b6000806000606084860312156133d057600080fd5b83356133db8161310f565b925060208401356133eb8161310f565b929592945050506040919091013590565b803563ffffffff8116811461341057600080fd5b919050565b60006020828403121561342757600080fd5b610fe9826133fc565b6000806040838503121561344357600080fd5b6131b9836133fc565b8015158114611ce957600080fd5b6000806040838503121561346d57600080fd5b82356001600160401b0381111561348357600080fd5b61348f858286016131c7565b92505060208301356134a08161344c565b809150509250929050565b815181526020808301519082015260408101610d5f565b803561ffff8116811461341057600080fd5b6000602082840312156134e657600080fd5b610fe9826134c2565b6000806040838503121561350257600080fd5b61350b836133fc565b9150613519602084016134c2565b90509250929050565b60008060006060848603121561353757600080fd5b613540846133fc565b925061354e602085016134c2565b915060408401356131908161344c565b60008060008060a0858703121561357457600080fd5b61357e86866132ac565b935060608501356001600160401b0381111561359957600080fd5b6135a5878288016132be565b90945092505060808501356135b98161310f565b939692955090935050565b60008083601f8401126135d657600080fd5b5081356001600160401b038111156135ed57600080fd5b6020830191508360208260051b8501011115612d2857600080fd5b6000806020838503121561361b57600080fd5b82356001600160401b0381111561363157600080fd5b61363d858286016135c4565b90969095509350505050565b6000806000806060858703121561365f57600080fd5b613668856133fc565b9350613676602086016134c2565b925060408501356001600160401b0381111561369157600080fd5b61369d878288016132be565b95989497509550505050565b600080600083850360808112156136bf57600080fd5b84356001600160401b038111156136d557600080fd5b6136e1878288016131c7565b9450506040601f19820112156136f657600080fd5b5060208401915060608401356131908161310f565b600060c082019050835182526001600160401b0360208501511660208301526040840151613746604084018280518252602090810151910152565b5082516080830152602083015160a0830152610fe9565b6000806040838503121561377057600080fd5b823561377b8161310f565b915060208301356134a08161310f565b60006060828403121561379d57600080fd5b610fe983836132ac565b600181811c908216806137bb57607f821691505b6020821081036131d957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d5f57610d5f6137db565b60008261382557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b60008235605e1983360301811261385657600080fd5b9190910192915050565b6000808335601e1984360301811261387757600080fd5b8301803591506001600160401b0382111561389157600080fd5b602001915036819003821315612d2857600080fd5b601f821115611d4e576000816000526020600020601f850160051c810160208610156138cf5750805b601f850160051c820191505b818110156138ee578281556001016138db565b505050505050565b6001600160401b0383111561390d5761390d613024565b6139218361391b83546137a7565b836138a6565b6000601f841160018114613955576000851561393d5750838201355b600019600387901b1c1916600186901b178355611b00565b600083815260209020601f19861690835b828110156139865786850135825560209485019460019092019101613966565b50868210156139a35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208082528181018390526000906040808401600586901b8501820187855b88811015613ab457878303603f190184528135368b9003605e19018112613a2357600080fd5b8a01606063ffffffff613a35836133fc565b16855261ffff613a468984016134c2565b168886015286820135601e19833603018112613a6157600080fd5b9091018781019190356001600160401b03811115613a7e57600080fd5b803603831315613a8d57600080fd5b8188870152613a9f82870182856139b5565b968901969550505091860191506001016139fd565b509098975050505050505050565b60008085851115613ad257600080fd5b83861115613adf57600080fd5b5050820193919092039150565b60008451613afe818460208901612fc1565b8201838582376000930192835250909392505050565b6020815260006112616020830184866139b5565b6000823561013e1983360301811261385657600080fd5b6001600160401b0381168114611ce957600080fd5b63ffffffff613b62896133fc565b1681526020880135602082015260006040890135613b7f81613b3f565b6001600160401b03811660408401525087606083015260e06080830152613baa60e0830187896139b5565b6001600160a01b03861660a084015282810360c0840152613bcc8185876139b5565b9a9950505050505050505050565b600060208284031215613bec57600080fd5b81516001600160401b03811115613c0257600080fd5b8201601f81018413613c1357600080fd5b8051613c216130d882613092565b818152856020838501011115613c3657600080fd5b612289826020830160208601612fc1565b600060208284031215613c5957600080fd5b8135610fe981613b3f565b60018060a01b038516815283602082015261ffff831660408201526080606082015260006110ba6080830184612fe5565b604081526000613ca86040830185612fe5565b82810360208401526122898185612fe5565b600060208284031215613ccc57600080fd5b8151610fe98161344c565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152613d0d60e0840182612fe5565b90506060850151603f198483030160a0850152613d2a8282612fe5565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215613d6257600080fd5b613d6a61303a565b9050815181526020820151602082015292915050565b600060408284031215613d9257600080fd5b610fe98383613d50565b6001600160f01b03198135818116916002851015613dc45780818660020360031b1b83161692505b505092915050565b600060408284031215613dde57600080fd5b613de661303a565b82358152602083013560208201528091505092915050565b80356020831015610d5f57600019602084900360031b1b1692915050565b6001600160c01b03198135818116916008851015613dc45760089490940360031b84901b1690921692915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c82015260008251613e8981602c850160208701612fc1565b91909101602c0195945050505050565b600060018201613eab57613eab6137db565b5060010190565b8481526001600160401b0360c01b8460c01b16602082015282602882015260008251613ee5816048850160208701612fc1565b9190910160480195945050505050565b81810381811115610d5f57610d5f6137db565b600060808284031215613f1a57600080fd5b604051606081018181106001600160401b0382111715613f3c57613f3c613024565b604052825181526020830151613f5181613b3f565b6020820152613f638460408501613d50565b60408201529392505050565b81516001600160401b03811115613f8857613f88613024565b613f9c81613f9684546137a7565b846138a6565b602080601f831160018114613fd15760008415613fb95750858301515b600019600386901b1c1916600185901b1785556138ee565b600085815260208120601f198616915b8281101561400057888601518255948401946001909101908401613fe1565b508582101561401e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610d5f57610d5f6137db565b60006020828403121561405357600080fd5b8151610fe98161310f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace000cb173d183337e25fab6cb85705c15aad6a58cb1d552ed71b9bc628c8a3de80072ab1bc1039b79dc4724ffca13de82c96834302d3c7e0d4252232d4b2dd8f900a2646970667358221220031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a164736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
-----Decoded View---------------
Arg [0] : _lzEndpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Deployed Bytecode Sourcemap
318:3406:52:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144:37;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;864:254:52;;;;;;;;;;-1:-1:-1;864:254:52;;;;;:::i;:::-;;:::i;:::-;;5114:186:37;;;;;;;;;;-1:-1:-1;5114:186:37;;;;;:::i;:::-;;:::i;:::-;;;3409:14:67;;3402:22;3384:41;;3372:2;3357:18;5114:186:37;3244:187:67;6517:1259:28;;;;;;;;;;-1:-1:-1;6517:1259:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;4798:149::-;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;5623:32:67;;;5605:51;;5593:2;5578:18;4798:149:28;5459:203:67;4921:708:11;;;;;;:::i;:::-;;:::i;2777:40:28:-;;;;;;;;;;;;2816:1;2777:40;;;;;7403:6:67;7391:19;;;7373:38;;7361:2;7346:18;2777:40:28;7229:188:67;3987:140:28;;;;;;;;;;-1:-1:-1;3987:140:28;;;-1:-1:-1;;;7592:52:67;;4118:1:28;7675:2:67;7660:18;;7653:59;7565:18;3987:140:28;7422:296:67;4512:325:29;;;;;;;;;;-1:-1:-1;4512:325:29;;;;;:::i;:::-;;:::i;1951:257:13:-;;;;;;;;;;-1:-1:-1;1951:257:13;;;887:1:12;8182:34:67;;759:1:11;8247:2:67;8232:18;;8225:43;8118:18;1951:257:13;7975:299:67;3850:152:37;;;;;;;;;;-1:-1:-1;3981:14:37;;3850:152;;;8425:25:67;;;8413:2;8398:18;3850:152:37;8279:177:67;2740:31:28;;;;;;;;;;;;2770:1;2740:31;;5892:244:37;;;;;;;;;;-1:-1:-1;5892:244:37;;;;;:::i;:::-;;:::i;3398:89:52:-;;;;;;;;;;-1:-1:-1;3398:89:52;;3479:1;9064:36:67;;9052:2;9037:18;3398:89:52;8922:184:67;3150:211:25;;;;;;;;;;-1:-1:-1;3150:211:25;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;3314:17:25;;;;;;;:8;:17;;;;;;3288:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3150:211;;;;;9690:13:67;;9705:6;9686:26;9668:45;;9783:4;9771:17;;;9765:24;9758:32;9751:40;9729:20;;;9722:70;;;;9641:18;3150:211:25;9468:330:67;3028:202:10;;;;;;;;;;-1:-1:-1;3028:202:10;;;;;:::i;:::-;;:::i;1814:111:52:-;;;;;;;;;;-1:-1:-1;1814:111:52;;;;;:::i;:::-;-1:-1:-1;;;;;1899:19:52;1876:4;1899:19;;;:9;:19;;;;;;;;;1814:111;8227:774:28;;;;;;;;;;-1:-1:-1;8227:774:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1553:257:25:-;;;;;;;;;;-1:-1:-1;1553:257:25;;;;;:::i;:::-;;:::i;1271:97:52:-;;;;;;;;;;-1:-1:-1;1325:7:52;1351:10;-1:-1:-1;;;;;1351:10:52;1271:97;;2068:93:15;;;;;;;;;;-1:-1:-1;2149:4:15;2068:93;;1532:222:14;;;;;;;;;;-1:-1:-1;1532:222:14;;;;;:::i;:::-;;:::i;17277:132:28:-;;;;;;;;;;-1:-1:-1;17277:132:28;;;;;:::i;:::-;2485:13:10;;;;;17359:4:28;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:28;;17277:132;2346:270:25;;;;;;;;;;-1:-1:-1;2346:270:25;;;;;:::i;:::-;;:::i;1035:46:10:-;;;;;;;;;;;;;;;799:143:29;;;;;;;;;;-1:-1:-1;753:24:29;923:12;799:143;;1928:316:25;;;;;;;;;;-1:-1:-1;1928:316:25;;;;;:::i;:::-;;:::i;5989:222:28:-;;;;;;;;;;-1:-1:-1;5989:222:28;;;;;:::i;:::-;;:::i;4035:171:37:-;;;;;;;;;;-1:-1:-1;4035:171:37;;;;;:::i;:::-;;:::i;3155:101:35:-;;;;;;;;;;;;;:::i;4060:128:11:-;;;;;;;;;;-1:-1:-1;4060:128:11;;;;;:::i;:::-;4149:12;4060:128;;;;;;;;-1:-1:-1;;;;;12817:31:67;;;12799:50;;12787:2;12772:18;4060:128:11;12655:200:67;2566:216:11;;;;;;;;;;-1:-1:-1;2566:216:11;;;;;:::i;:::-;-1:-1:-1;;;;;2751:24:11;;2770:4;2751:24;2566:216;;;;;;;1124:141:52;;;;;;;;;;-1:-1:-1;1124:141:52;;;;;:::i;:::-;;:::i;1593:215::-;;;;;;;;;;-1:-1:-1;1593:215:52;;;;;:::i;:::-;;:::i;2441:144:35:-;;;;;;;;;;;;;:::i;2954:148:37:-;;;;;;;;;;;;;:::i;2434:46:28:-;;;;;;;;;;;;;;;2026:94:30;;;;;;;;;;-1:-1:-1;2085:4:30;2026:94;;4401:178:37;;;;;;;;;;-1:-1:-1;4401:178:37;;;;;:::i;:::-;;:::i;1596:180:15:-;;;;;;;;;;;;;:::i;2513:600:14:-;;;;;;;;;;-1:-1:-1;2513:600:14;;;;;:::i;:::-;;:::i;2342:163:10:-;;;;;;;;;;-1:-1:-1;2342:163:10;;;;;:::i;:::-;2485:13;;2400:7;2485:13;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;;2342:163;3872:1058:14;;;;;;;;;;-1:-1:-1;3872:1058:14;;;;;:::i;:::-;;:::i;2922:150:25:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;3050:15:25;;;2922:150;;2978:1333:15;;;;;;:::i;:::-;;:::i;9689:290:28:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;4123:105:10:-;;;;;;;;;;-1:-1:-1;4123:105:10;;;;;:::i;:::-;;:::i;4959:409:15:-;;;;;;:::i;:::-;;:::i;2293:226::-;;;;;;;;;;-1:-1:-1;2293:226:15;;;;;:::i;:::-;;:::i;4612:195:37:-;;;;;;;;;;-1:-1:-1;4612:195:37;;;;;:::i;:::-;;:::i;530:47:25:-;;;;;;;;;;;;571:6;530:47;;1374:213:52;;;;;;;;;;-1:-1:-1;1374:213:52;;;;;:::i;:::-;;:::i;3405:215:35:-;;;;;;;;;;-1:-1:-1;3405:215:35;;;;;:::i;:::-;;:::i;3324:149:11:-;;;;;;;;;;-1:-1:-1;3324:149:11;;;;;:::i;:::-;;:::i;2697:144:37:-;2827:7;2820:14;;2742:13;;-1:-1:-1;;;;;;;;;;;2064:20:37;2820:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2697:144;:::o;864:254:52:-;4158:30:36;4191:26;:24;:26::i;:::-;4302:15;;4158:59;;-1:-1:-1;4302:15:36;-1:-1:-1;;;4302:15:36;;;4301:16;;-1:-1:-1;;;;;4348:14:36;4279:19;4724:16;;:34;;;;;4744:14;4724:34;4704:54;;4768:17;4788:11;-1:-1:-1;;;;;4788:16:36;4803:1;4788:16;:50;;;;-1:-1:-1;4816:4:36;4808:25;:30;4788:50;4768:70;;4854:12;4853:13;:30;;;;;4871:12;4870:13;4853:30;4849:91;;;4906:23;;-1:-1:-1;;;4906:23:36;;;;;;;;;;;4849:91;4949:18;;-1:-1:-1;;4949:18:36;4966:1;4949:18;;;4977:67;;;;5011:22;;-1:-1:-1;;;;5011:22:36;-1:-1:-1;;;5011:22:36;;;4977:67;1006:37:52::1;1017:5;1024:7;1033:9;1006:10;:37::i;:::-;1053:25;1068:9;1053:14;:25::i;:::-;1109:1;1088:23:::0;;-1:-1:-1;;;;;;1088:23:52::1;::::0;;5064:101:36;;;;5098:23;;-1:-1:-1;;;;5098:23:36;;;5140:14;;-1:-1:-1;12799:50:67;;5140:14:36;;12787:2:67;12772:18;5140:14:36;;;;;;;5064:101;4092:1079;;;;;864:254:52;;;:::o;5114:186:37:-;5187:4;966:10:38;5241:31:37;966:10:38;5257:7:37;5266:5;5241:8;:31::i;:::-;5289:4;5282:11;;;5114:186;;;;;:::o;6517:1259:28:-;-1:-1:-1;;;;;;;;;;;;;;;;;6669:35:28;6706:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;6706:28:28;6925:34;;;;;;;;-1:-1:-1;6925:34:28;;;-1:-1:-1;;6925:34:28;;;;;;;7076:21;;;;;;;;;;;6925:34;;-1:-1:-1;;;7076:21:28;;;-1:-1:-1;;;;;;;;;;;;;;;;;7076:21:28;;;;;;;;;;;;;;;-1:-1:-1;7060:37:28;-1:-1:-1;7534:20:28;;7584:120;7608:19;;;;7641:22;;;;7677:17;;;;7608:10;7677:17;:::i;:::-;7584:10;:120::i;:::-;7727:42;;;;;;;;;;;;;;;;6517:1259;;;;-1:-1:-1;;;;;;6517:1259:28:o;4798:149::-;4843:7;;2993:25;4889:20;4926:14;-1:-1:-1;;;;;4926:14:28;;4798:149;-1:-1:-1;;4798:149:28:o;4921:708:11:-;5234:8;-1:-1:-1;;;;;5226:31:11;5247:10;5226:31;5222:68;;5266:24;;-1:-1:-1;;;5266:24:11;;5279:10;5266:24;;;5605:51:67;5578:18;;5266:24:11;;;;;;;;5222:68;5426:14;;;;;;5390:32;;5407:14;;5426:7;5407:14;:::i;:::-;5390:16;:32::i;:::-;:50;5386:103;;5458:14;;;;:7;:14;:::i;:::-;5449:40;;-1:-1:-1;;;5449:40:11;;18392:10:67;18380:23;;;5449:40:11;;;18362:42:67;5474:14:11;;;;18420:18:67;;;18413:34;18335:18;;5449:40:11;18190:263:67;5386:103:11;5563:59;5574:7;5583:5;5590:8;;5600:9;5611:10;;5563;:59::i;:::-;4921:708;;;;;;;:::o;4512:325:29:-;2334:13:35;:11;:13::i;:::-;753:24:29;4649:12;;4576:23:::1;4675:12:::0;;;4671:43:::1;;4696:18;;-1:-1:-1::0;;;4696:18:29::1;;;;;;;;;;;4671:43;4740:1;4725:16:::0;;4751:38:::1;4769:4;4776:3:::0;4781:7;4751:9:::1;:38::i;:::-;4817:3;-1:-1:-1::0;;;;;4804:26:29::1;;4822:7;4804:26;;;;8425:25:67::0;;8413:2;8398:18;;8279:177;4804:26:29::1;;;;;;;;4566:271;;4512:325:::0;:::o;5892:244:37:-;5979:4;966:10:38;6035:37:37;6051:4;966:10:38;6066:5:37;6035:15;:37::i;:::-;6082:26;6092:4;6098:2;6102:5;6082:9;:26::i;:::-;6125:4;6118:11;;;5892:244;;;;;;:::o;3028:202:10:-;2334:13:35;:11;:13::i;:::-;3167::10::1;::::0;::::1;3108:25;3167:13:::0;;;-1:-1:-1;;;;;;;;;;;3167:13:10::1;::::0;;;;;;;;:21;;;3203:20;;18362:42:67;;;18420:18;;18413:34;;;926:26:10;3203:20:::1;::::0;18335:18:67;3203:20:10::1;;;;;;;;3098:132;3028:202:::0;;:::o;8227:774:28:-;-1:-1:-1;;;;;;;;;;;;;;;;;8561:24:28;8589:74;8600:19;;;;8621:22;;;;8645:17;;;;8600:10;8645:17;:::i;8589:74::-;8558:105;;;8752:20;8774;8798:49;8818:10;8830:16;8798:19;:49::i;:::-;8751:96;;-1:-1:-1;8751:96:28;-1:-1:-1;8936:58:28;8943:17;;;;:10;:17;:::i;:::-;8962:7;8971;8980:13;8936:6;:58::i;:::-;8929:65;8227:774;-1:-1:-1;;;;;;8227:774:28:o;1553:257:25:-;2334:13:35;:11;:13::i;:::-;571:6:25::1;1628:25;::::0;::::1;;1624:55;;;1662:17;;-1:-1:-1::0;;;1662:17:25::1;;;;;;;;;;;1624:55;-1:-1:-1::0;;;;;;;;;;;1738:25:25;;-1:-1:-1;;1738:25:25::1;;::::0;::::1;::::0;;::::1;::::0;;1778::::1;::::0;7373:38:67;;;1778:25:25::1;::::0;7361:2:67;7346:18;1778:25:25::1;;;;;;;;1614:196;1553:257:::0;:::o;1532:222:14:-;1714:23;;;1632:33;1714:23;;;1151:36;1714:23;;;;;;;;:33;;;;;;;;;;;1707:40;;1608:12;;1151:36;1714:33;1707:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1532:222;;;;:::o;2346:270:25:-;2424:7;2443:10;2456:19;2467:7;2456:10;:19::i;:::-;2443:32;-1:-1:-1;2561:8:25;;;;:48;;571:6;2577:13;2576:33;2577:13;;:7;:13;:::i;:::-;2576:33;;;;:::i;:::-;2561:48;;;2572:1;2561:48;2554:55;2346:270;-1:-1:-1;;;;2346:270:25:o;1928:316::-;2334:13:35;:11;:13::i;:::-;571:6:25::1;2027:25;::::0;::::1;;2023:55;;;2061:17;;-1:-1:-1::0;;;2061:17:25::1;;;;;;;;;;;2023:55;2088:20;-1:-1:-1::0;;;;;;;;;;;2157:28:25::1;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;2137:17:::1;::::0;::::1;-1:-1:-1::0;2137:17:25;;;:8:::1;::::0;::::1;:17:::0;;;;;:48;;;;;;::::1;;::::0;::::1;-1:-1:-1::0;;2137:48:25;;;;::::1;::::0;;;;::::1;::::0;;;2200:37;;19177:42:67;;;19235:18;;;19228:47;19291:18;;;19284:50;2137:8:25;;-1:-1:-1;2200:37:25::1;::::0;19165:2:67;19150:18;2200:37:25::1;;;;;;;2013:231;1928:316:::0;;;:::o;5989:222:28:-;2334:13:35;:11;:13::i;:::-;2993:25:28;6129:30;;-1:-1:-1;;;;;;6129:30:28::1;-1:-1:-1::0;;;;;6129:30:28;::::1;::::0;;::::1;::::0;;6174::::1;::::0;5605:51:67;;;6174:30:28::1;::::0;5593:2:67;5578:18;6174:30:28::1;5459:203:67::0;4035:171:37;-1:-1:-1;;;;;4179:20:37;4100:7;4179:20;;;-1:-1:-1;;;;;;;;;;;4179:20:37;;;;;;;4035:171::o;3155:101:35:-;2334:13;:11;:13::i;:::-;3219:30:::1;3246:1;3219:18;:30::i;:::-;3155:101::o:0;1124:141:52:-;2334:13:35;:11;:13::i;:::-;1197:10:52::1;:24:::0;;-1:-1:-1;;;;;;1197:24:52::1;-1:-1:-1::0;;;;;1197:24:52;::::1;::::0;;::::1;::::0;;;1236:22:::1;::::0;5605:51:67;;;1236:22:52::1;::::0;5593:2:67;5578:18;1236:22:52::1;;;;;;;1124:141:::0;:::o;1593:215::-;2334:13:35;:11;:13::i;:::-;-1:-1:-1;;;;;1677:19:52;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1669:47;;;::::0;-1:-1:-1;;;1669:47:52;;19547:2:67;1669:47:52::1;::::0;::::1;19529:21:67::0;19586:2;19566:18;;;19559:30;-1:-1:-1;;;19605:18:67;;;19598:45;19660:18;;1669:47:52::1;19345:339:67::0;1669:47:52::1;-1:-1:-1::0;;;;;1726:19:52;::::1;1748:5;1726:19:::0;;;:9:::1;:19;::::0;;;;;;;:27;;-1:-1:-1;;1726:27:52::1;::::0;;1768:33;3384:41:67;;;1768:33:52::1;::::0;3357:18:67;1768:33:52::1;;;;;;;;1593:215:::0;:::o;2441:144:35:-;2487:7;;1313:22;2533:20;1192:159;2954:148:37;3086:9;3079:16;;3001:13;;-1:-1:-1;;;;;;;;;;;2064:20:37;3079:16;;;:::i;4401:178::-;4470:4;966:10:38;4524:27:37;966:10:38;4541:2:37;4545:5;4524:9;:27::i;1596:180:15:-;1648:7;;1200:41;1708:34;1050:207;2513:600:14;2334:13:35;:11;:13::i;:::-;1151:36:14;2625:33:::1;2700:356;2720:27:::0;;::::1;2700:356;;;2882:48;2902:16;;2919:1;2902:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2882:19;:48::i;:::-;3018:16;;3035:1;3018:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2944:1:::0;:17:::1;2962:16:::0;;2979:1;2962:19;;::::1;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:23;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;2944:42;;;;;;;;;;;;;;;:71;2987:16;;3004:1;2987:19;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:27;::::0;;;;;::::1;;;:::i;:::-;2944:71;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;2944:71:14;;:101:::1;::::0;;:71;:101:::1;:::i;:::-;-1:-1:-1::0;2749:3:14::1;;2700:356;;;;3071:35;3089:16;;3071:35;;;;;;;:::i;3872:1058::-:0;4138:23;;;4039:33;4138:23;;;1151:36;4138:23;;;;;;;;:33;;;;;;;;;;4114:57;;4015:12;;4039:33;4138;4114:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4300:8;:15;4319:1;4300:20;4296:46;;4329:13;;4322:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4322:20:14;;-1:-1:-1;4322:20:14;;-1:-1:-1;;;;;4322:20:14;4296:46;4427:1;4403:25;;;4399:46;;4437:8;-1:-1:-1;4430:15:14;;-1:-1:-1;4430:15:14;4399:46;4592:1;4568:25;;4564:267;;4609:34;4629:13;;4609:19;:34::i;:::-;4792:8;4802:17;:13;4816:1;4802:13;;:17;:::i;:::-;4779:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4772:48;;;;;;4564:267;4909:13;;4894:29;;-1:-1:-1;;;4894:29:14;;;;;;;;;:::i;2978:1333:15:-;3079:9;3074:1037;3094:19;;;3074:1037;;;3134:29;3166:8;;3175:1;3166:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;3134:43;-1:-1:-1;3260:50:15;3267:20;;;;3134:43;3267:20;:::i;:::-;3289;;;;2485:13:10;;;;;17359:4:28;2485:13:10;;;-1:-1:-1;;;;;;;;;;;2485:13:10;;;;;;17382:20:28;;17277:132;3260:50:15;3255:65;;3312:8;;;3255:65;3882:4;:22;3913:12;;;;:6;3976:11;;;;4005:14;;;;3913:6;4005:14;:::i;:::-;4037:15;;;;;;;;:::i;:::-;4070:16;;;;:6;:16;:::i;:::-;3882:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3120:991;3074:1037;3115:3;;3074:1037;;;;4268:10;-1:-1:-1;;;;;4258:43:15;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4258:45:15;;;;;;;;;;;;:::i;:::-;4241:63;;-1:-1:-1;;;4241:63:15;;;;;;;;:::i;9689:290:28:-;9850:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9933:39:28;9939:10;9951:4;9957:14;9933:5;:39::i;:::-;9926:46;;;;9689:290;;;;;;:::o;4123:105:10:-;2334:13:35;:11;:13::i;:::-;4190:31:10::1;::::0;-1:-1:-1;;;4190:31:10;;-1:-1:-1;;;;;5623:32:67;;;4190:31:10::1;::::0;::::1;5605:51:67::0;4190:8:10::1;:20;::::0;::::1;::::0;5578:18:67;;4190:31:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;4123:105:::0;:::o;4959:409:15:-;5238:10;5260:4;5238:27;5234:50;;5274:10;;-1:-1:-1;;;5274:10:15;;;;;;;;;;;5234:50;5294:67;5313:7;5322:5;5329:8;;5339:9;5350:10;;5294:18;:67::i;2293:226::-;2334:13:35;:11;:13::i;:::-;1200:41:15;2453:22;;-1:-1:-1;;;;;;2453:22:15::1;-1:-1:-1::0;;;;;2453:22:15;::::1;::::0;;::::1;::::0;;2490::::1;::::0;5605:51:67;;;2490:22:15::1;::::0;5593:2:67;5578:18;2490:22:15::1;5459:203:67::0;4612:195:37;-1:-1:-1;;;;;4771:20:37;;;4692:7;4771:20;;;:13;:20;;;;;;;;:29;;;;;;;;;;;;;4612:195::o;1374:213:52:-;2334:13:35;:11;:13::i;:::-;-1:-1:-1;;;;;1454:19:52;::::1;;::::0;;;:9:::1;:19;::::0;;;;;::::1;;1453:20;1445:52;;;::::0;-1:-1:-1;;;1445:52:52;;28172:2:67;1445:52:52::1;::::0;::::1;28154:21:67::0;28211:2;28191:18;;;28184:30;-1:-1:-1;;;28230:18:67;;;28223:49;28289:18;;1445:52:52::1;27970:343:67::0;1445:52:52::1;-1:-1:-1::0;;;;;1507:19:52;::::1;;::::0;;;1529:4:::1;1507:19;::::0;;;;;;;;:26;;-1:-1:-1;;1507:26:52::1;::::0;::::1;::::0;;1548:32;;3384:41:67;;;1548:32:52::1;::::0;3357:18:67;1548:32:52::1;3244:187:67::0;3405:215:35;2334:13;:11;:13::i;:::-;-1:-1:-1;;;;;3489:22:35;::::1;3485:91;;3534:31;::::0;-1:-1:-1;;;3534:31:35;;3562:1:::1;3534:31;::::0;::::1;5605:51:67::0;5578:18;;3534:31:35::1;5459:203:67::0;3485:91:35::1;3585:28;3604:8;3585:18;:28::i;:::-;3405:215:::0;:::o;3324:149:11:-;3406:4;3453:13;;;;;;3429:20;;3435:13;;3453:6;3435:13;:::i;3429:20::-;:37;;3324:149;-1:-1:-1;;3324:149:11:o;9071:205:36:-;9129:30;;3147:66;9186:27;8819:122;1160:189:30;6929:20:36;:18;:20::i;:::-;1279:28:30::1;1292:5;1299:7;1279:12;:28::i;:::-;1317:25;1332:9;1317:14;:25::i;:::-;1160:189:::0;;;:::o;1847:127:35:-;6929:20:36;:18;:20::i;:::-;1929:38:35::1;1954:12;1929:24;:38::i;9905:128:37:-:0;9989:37;9998:5;10005:7;10014:5;10021:4;9989:8;:37::i;2335:691:29:-;2555:9;2482:20;;2739:26;2746:7;2555:9;2739:6;:26::i;:::-;2725:40;;2818:28;2842:3;2830:9;:15;2818:11;:28::i;:::-;2799:47;;2926:12;2907:16;:31;2903:117;;;2961:48;;-1:-1:-1;;;2961:48:29;;;;;28492:25:67;;;28533:18;;;28526:34;;;28465:18;;2961:48:29;28318:248:67;2903:117:29;2530:496;2335:691;;;;;;:::o;3528:257:10:-;3691:13;;;3598:7;3691:13;;;-1:-1:-1;;;;;;;;;;;3691:13:10;;;;;;;;;3714:43;;3745:12;;-1:-1:-1;;;3745:12:10;;28745:10:67;28733:23;;3745:12:10;;;28715:42:67;28688:18;;3745:12:10;28571:192:67;14070:1806:28;14547:17;14567:36;:17;:8;;:15;:17::i;:::-;2891:2:34;2780:123;14567:36:28;14547:56;;14736:24;14763:62;14771:9;14782:26;14788:19;:8;;:17;:19::i;:::-;14782:5;:26::i;:::-;14810:14;;;;:7;:14;:::i;:::-;14763:7;:62::i;:::-;14736:89;-1:-1:-1;243:2:34;-1:-1:-1;;14836:955:28;;;14940:23;14966:175;15009:13;;;;;;;;:::i;:::-;15040:14;;;;:7;:14;:::i;:::-;15072:16;15106:21;:8;;:19;:21::i;:::-;14966:25;:175::i;:::-;15688:92;;-1:-1:-1;;;15688:92:28;;14940:201;;-1:-1:-1;;;;;;15688:8:28;:20;;;;:92;;15709:9;;15720:5;;15727:1;;14940:201;;15688:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14863:928;14836:955;-1:-1:-1;;;;;15806:63:28;;15818:5;15806:63;15825:14;;;;:7;:14;:::i;:::-;15806:63;;;18392:10:67;18380:23;;;18362:42;;18435:2;18420:18;;18413:34;;;18335:18;15806:63:28;;;;;;;14373:1503;;14070:1806;;;;;;;:::o;2658:162:35:-;966:10:38;2717:7:35;:5;:7::i;:::-;-1:-1:-1;;;;;2717:23:35;;2713:101;;2763:40;;-1:-1:-1;;;2763:40:35;;966:10:38;2763:40:35;;;5605:51:67;5578:18;;2763:40:35;5459:203:67;6509:300:37;-1:-1:-1;;;;;6592:18:37;;6588:86;;6633:30;;-1:-1:-1;;;6633:30:37;;6660:1;6633:30;;;5605:51:67;5578:18;;6633:30:37;5459:203:67;6588:86:37;-1:-1:-1;;;;;6687:16:37;;6683:86;;6726:32;;-1:-1:-1;;;6726:32:37;;6755:1;6726:32;;;5605:51:67;5578:18;;6726:32:37;5459:203:67;6683:86:37;6778:24;6786:4;6792:2;6796:5;6778:7;:24::i;11649:476::-;11748:24;11775:25;11785:5;11792:7;11775:9;:25::i;:::-;11748:52;;-1:-1:-1;;11814:16:37;:36;11810:309;;;11889:5;11870:16;:24;11866:130;;;11921:60;;-1:-1:-1;;;11921:60:37;;-1:-1:-1;;;;;29990:32:67;;11921:60:37;;;29972:51:67;30039:18;;;30032:34;;;30082:18;;;30075:34;;;29945:18;;11921:60:37;29770:345:67;11866:130:37;12037:57;12046:5;12053:7;12081:5;12062:16;:24;12088:5;12037:8;:57::i;:::-;11738:387;11649:476;;;:::o;12056:1496:28:-;12188:20;12210;12242:15;12413:324;12445:10;:13;;;12472:16;12478:9;12472:5;:16::i;:::-;12706:21;;;;:10;:21;:::i;:::-;12413:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12413:18:28;;-1:-1:-1;;;12413:324:28:i;:::-;12389:348;;-1:-1:-1;12389:348:28;-1:-1:-1;12817:14:28;12389:348;12834:33;;2770:1;12834:33;;;2816:1;12834:33;12817:50;-1:-1:-1;12989:67:28;13004:17;;;;:10;:17;:::i;:::-;13023:7;13032:23;;;;:10;:23;:::i;12989:67::-;2993:25;13372:14;;12979:77;;-1:-1:-1;2993:25:28;-1:-1:-1;;;;;13372:14:28;13466:23;;13462:83;;13491:54;;-1:-1:-1;;;13491:54:28;;-1:-1:-1;;;;;13491:36:28;;;;;:54;;13528:7;;13537;;13491:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;13462:83;12232:1320;;;;12056:1496;;;;;:::o;2550:391:12:-;-1:-1:-1;;;;;;;;;;;;;;;;;2771:8:12;-1:-1:-1;;;;;2771:14:12;;2803:86;;;;;;;;2819:7;2803:86;;;;;;2828:25;2845:7;2828:16;:25::i;:::-;2803:86;;;;2855:8;2803:86;;;;2865:8;2803:86;;;;2875:13;2803:86;;;;;2915:4;2771:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2752:182;2550:391;-1:-1:-1;;;;;2550:391:12:o;2622:241:25:-;2774:17;;;2681:6;2774:17;;;:8;:17;;;;;;;;2748:43;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1421:20:25;2808:48;;2841:15;;;;2808:48;;;2825:13;;2801:55;-1:-1:-1;;;2622:241:25:o;3774:248:35:-;1313:22;3923:8;;-1:-1:-1;;;;;;3941:19:35;;-1:-1:-1;;;;;3941:19:35;;;;;;;;3975:40;;3923:8;;;;;3975:40;;3847:24;;3975:40;3837:185;;3774:248;:::o;5070:218:14:-;5156:18;5191:13;5202:1;5156:18;5191:8;;:13;:::i;:::-;5184:21;;;:::i;:::-;5177:29;;;-1:-1:-1;1003:1:14;5220:28;;5216:65;;5272:8;;5257:24;;-1:-1:-1;;;5257:24:14;;;;;;;;;:::i;10429:1333:28:-;10583:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;10981:20:28;;11031:140;11051:10;11075:19;;;;11108:22;;;;11144:17;;;;11075:10;11144:17;:::i;:::-;11031:6;:140::i;:::-;10980:191;;;;11260:20;11282;11306:49;11326:10;11338:16;11306:19;:49::i;:::-;11259:96;;-1:-1:-1;11259:96:28;-1:-1:-1;11478:66:28;11486:17;;;;:10;:17;:::i;:::-;11505:7;11514;11478:66;;;;;;;11523:4;11478:66;:::i;:::-;11529:14;11478:7;:66::i;:::-;11610:42;;;;;;;;;;;;;;;;;;;11676:15;;11465:79;;-1:-1:-1;11610:42:28;;-1:-1:-1;11712:10:28;;11676:15;11668:87;;11693:17;;;;:10;:17;:::i;:::-;11668:87;;;33101:10:67;33089:23;;;33071:42;;33144:2;33129:18;;33122:34;;;33172:18;;33165:34;;;33059:2;33044:18;11668:87:28;;;;;;;10649:1113;;;;10429:1333;;;;;;:::o;7082:141:36:-;7149:17;:15;:17::i;:::-;7144:73;;7189:17;;-1:-1:-1;;;7189:17:36;;;;;;;;;;;2263:147:37;6929:20:36;:18;:20::i;:::-;2365:38:37::1;2388:5;2395:7;2365:22;:38::i;:::-;2263:147:::0;;:::o;4539:183:28:-;6929:20:36;:18;:20::i;:::-;4618:22:28::1;4630:9;4618:11;:22::i;:::-;4650:30;:28;:30::i;:::-;4690:25;:23;:25::i;1980:235:35:-:0;6929:20:36;:18;:20::i;10880:487:37:-;-1:-1:-1;;;;;;;;;;;;;;;;11045:19:37;;11041:89;;11087:32;;-1:-1:-1;;;11087:32:37;;11116:1;11087:32;;;5605:51:67;5578:18;;11087:32:37;5459:203:67;11041:89:37;-1:-1:-1;;;;;11143:21:37;;11139:90;;11187:31;;-1:-1:-1;;;11187:31:37;;11215:1;11187:31;;;5605:51:67;5578:18;;11187:31:37;5459:203:67;11139:90:37;-1:-1:-1;;;;;11238:20:37;;;;;;;:13;;;:20;;;;;;;;:29;;;;;;;;;:37;;;11285:76;;;;11335:7;-1:-1:-1;;;;;11319:31:37;11328:5;-1:-1:-1;;;;;11319:31:37;;11344:5;11319:31;;;;8425:25:67;;8413:2;8398:18;;8279:177;11319:31:37;;;;;;;;10978:389;10880:487;;;;:::o;17803:172:28:-;17874:16;17947:21;17910:33;17947:21;17910:9;:33;:::i;:::-;17909:59;;;;:::i;1573:123:34:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:34:o;18199:139:28:-;18263:16;18298:33;18310:21;-1:-1:-1;;;;;18298:33:28;;;:::i;3505:462:30:-;3639:24;-1:-1:-1;;;;;3679:19:30;;3675:46;;3714:6;3700:21;;3675:46;3817:21;3823:3;3828:9;3817:5;:21::i;:::-;-1:-1:-1;3951:9:30;;3505:462;-1:-1:-1;;3505:462:30:o;2186:130:34:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:34;;2186:130;-1:-1:-1;;;;;;2186:130:34:o;640:284:33:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;3493:229:52:-;3587:30;3601:4;3607:2;3611:5;3587:13;:30::i;:::-;3627:5;:7;;;:5;:7;;;:::i;:::-;;;;;;3670:5;;3666:2;-1:-1:-1;;;;;3649:66:52;3660:4;-1:-1:-1;;;;;3649:66:52;;3677:5;3684:15;3694:4;3684:9;:15::i;:::-;3701:13;3711:2;3701:9;:13::i;:::-;3649:66;;;34721:25:67;;;34777:2;34762:18;;34755:34;;;;34805:18;;;34798:34;34709:2;34694:18;3649:66:52;;;;;;;3493:229;;;:::o;18738:266:28:-;18803:15;;18850:33;18862:21;18850:9;:33;:::i;:::-;18830:53;-1:-1:-1;;;;;;18897:28:28;;18893:70;;;18934:29;;-1:-1:-1;;;18934:29:28;;;;;8425:25:67;;;8398:18;;18934:29:28;8279:177:67;598:506:34;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;34998:19:67;;;35073:3;35051:16;-1:-1:-1;;;;;;35047:51:67;35042:2;35033:12;;35026:73;35124:2;35115:12;;34843:290;1057:40:34;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;1931:1036:52:-;-1:-1:-1;;;;;2185:16:52;;2092:20;2185:16;;;:9;:16;;;;;;2092:20;;2185:16;;:130;;2271:44;2282:9;2293:12;2307:7;2271:10;:44::i;:::-;2185:130;;;2216:40;2232:9;2243:12;2216:15;:40::i;:::-;2150:165;;-1:-1:-1;2150:165:52;-1:-1:-1;2329:31:52;;;2325:122;;;2376:60;;-1:-1:-1;;;2376:60:52;;35877:2:67;2376:60:52;;;35859:21:67;35916:2;35896:18;;;35889:30;35955:34;35935:18;;;35928:62;-1:-1:-1;;;36006:18:67;;;35999:48;36064:19;;2376:60:52;35675:414:67;2325:122:52;2456:11;2470:31;2485:16;2470:12;:31;:::i;:::-;2456:45;-1:-1:-1;2516:7:52;;2512:409;;2565:1;2543:10;-1:-1:-1;;;;;2543:10:52;2539:372;;753:24:29;2682:19:52;;;;;;2737:36;2747:5;2762:4;2682:19;2737:9;:36::i;:::-;2569:219;2539:372;;;2880:10;;2863:33;;2873:5;;-1:-1:-1;;;;;2880:10:52;2892:3;2863:9;:33::i;:::-;2930:30;2936:5;2943:16;2930:5;:30::i;:::-;2140:827;1931:1036;;;;;;;:::o;3700:766:12:-;3901:31;;:::i;:::-;4066:20;4089:26;4100:4;:14;;;4089:10;:26::i;:::-;4129:15;;;;4066:49;;-1:-1:-1;4129:19:12;4125:53;;4150:28;4162:4;:15;;;4150:11;:28::i;:::-;4267:8;-1:-1:-1;;;;;4267:13:12;;4289:12;4321:92;;;;;;;;4337:7;4321:92;;;;;;4346:25;4363:7;4346:16;:25::i;:::-;4321:92;;;;4373:8;4321:92;;;;4383:8;4321:92;;;;4411:1;4393:4;:15;;;:19;4321:92;;;;;4431:14;4267:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4189:270;3700:766;-1:-1:-1;;;;;;;3700:766:12:o;8485:120:36:-;8535:4;8558:26;:24;:26::i;:::-;:40;-1:-1:-1;;;8558:40:36;;;;;;-1:-1:-1;8485:120:36:o;2416:216:37:-;6929:20:36;:18;:20::i;:::-;-1:-1:-1;;;;;;;;;;;2581:7:37;:15:::1;2591:5:::0;2581:7;:15:::1;:::i;:::-;-1:-1:-1::0;2606:9:37::1;::::0;::::1;:19;2618:7:::0;2606:9;:19:::1;:::i;1456:189:13:-:0;6929:20:36;:18;:20::i;:::-;1532:26:13::1;1548:9;1532:15;:26::i;1438:68:15:-:0;6929:20:36;:18;:20::i;8637:208:37:-;-1:-1:-1;;;;;8707:21:37;;8703:91;;8751:32;;-1:-1:-1;;;8751:32:37;;8780:1;8751:32;;;5605:51:67;5578:18;;8751:32:37;5459:203:67;8703:91:37;8803:35;8819:1;8823:7;8832:5;8803:7;:35::i;7124:1170::-;-1:-1:-1;;;;;;;;;;;;;;;;7266:18:37;;7262:546;;7420:5;7402:1;:14;;;:23;;;;;;;:::i;:::-;;;;-1:-1:-1;7262:546:37;;-1:-1:-1;7262:546:37;;-1:-1:-1;;;;;7478:17:37;;7456:19;7478:17;;;;;;;;;;;7513:19;;;7509:115;;;7559:50;;-1:-1:-1;;;7559:50:37;;-1:-1:-1;;;;;29990:32:67;;7559:50:37;;;29972:51:67;30039:18;;;30032:34;;;30082:18;;;30075:34;;;29945:18;;7559:50:37;29770:345:67;7509:115:37;-1:-1:-1;;;;;7744:17:37;;:11;:17;;;;;;;;;;7764:19;;;;7744:39;;7262:546;-1:-1:-1;;;;;7822:16:37;;7818:429;;7985:14;;;:23;;;;;;;7818:429;;;-1:-1:-1;;;;;8198:15:37;;:11;:15;;;;;;;;;;:24;;;;;;7818:429;8277:2;-1:-1:-1;;;;;8262:25:37;8271:4;-1:-1:-1;;;;;8262:25:37;;8281:5;8262:25;;;;8425::67;;8413:2;8398:18;;8279:177;8262:25:37;;;;;;;;7199:1095;7124:1170;;;:::o;2973:419:52:-;3165:9;3092:20;3227:22;3165:9;3227:11;:22::i;:::-;3208:41;;3292:12;3273:16;:31;3269:117;;;3327:48;;-1:-1:-1;;;3327:48:52;;;;;28492:25:67;;;28533:18;;;28526:34;;;28465:18;;3327:48:52;28318:248:67;3269:117:52;2973:419;;;;;:::o;9163:206:37:-;-1:-1:-1;;;;;9233:21:37;;9229:89;;9277:30;;-1:-1:-1;;;9277:30:37;;9304:1;9277:30;;;5605:51:67;5578:18;;9277:30:37;5459:203:67;9229:89:37;9327:35;9335:7;9352:1;9356:5;9327:7;:35::i;5162:191:12:-;5228:17;5274:10;5261:9;:23;5257:62;;5293:26;;-1:-1:-1;;;5293:26:12;;5309:9;5293:26;;;8425:25:67;8398:18;;5293:26:12;8279:177:67;5257:62:12;-1:-1:-1;5336:10:12;5162:191::o;5730:410::-;5883:15;5901:8;-1:-1:-1;;;;;5901:16:12;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5883:36;-1:-1:-1;;;;;;5933:21:12;;5929:54;;5963:20;;-1:-1:-1;;;5963:20:12;;;;;;;;;;;5929:54;6057:76;-1:-1:-1;;;;;6057:32:12;;6090:10;6110:8;6121:11;6057:32;:76::i;1787:123:10:-;6929:20:36;:18;:20::i;:::-;1867:36:10::1;1893:9;1867:25;:36::i;1618:188:47:-:0;1745:53;;;-1:-1:-1;;;;;38905:15:67;;;1745:53:47;;;38887:34:67;38957:15;;38937:18;;;38930:43;38989:18;;;;38982:34;;;1745:53:47;;;;;;;;;;38822:18:67;;;;1745:53:47;;;;;;;;-1:-1:-1;;;;;1745:53:47;-1:-1:-1;;;1745:53:47;;;1718:81;;1738:5;;1718:19;:81::i;1916:191:10:-;6929:20:36;:18;:20::i;:::-;-1:-1:-1;;;;;2010:23:10;::::1;2006:53;;2042:17;;-1:-1:-1::0;;;2042:17:10::1;;;;;;;;;;;8370:720:47::0;8450:18;8478:19;8616:4;8613:1;8606:4;8600:11;8593:4;8587;8583:15;8580:1;8573:5;8566;8561:60;8673:7;8663:176;;8717:4;8711:11;8762:16;8759:1;8754:3;8739:40;8808:16;8803:3;8796:29;8663:176;-1:-1:-1;;8916:1:47;8910:8;8866:16;;-1:-1:-1;8942:15:47;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:47;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:47;;-1:-1:-1;;;;;5623:32:67;;9033:40:47;;;5605:51:67;5578:18;;9033:40:47;5459:203:67;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:67:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:67;238:16;;231:27;14:250::o;269:271::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;522:2;501:15;-1:-1:-1;;497:29:67;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:67:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:127::-;831:10;826:3;822:20;819:1;812:31;862:4;859:1;852:15;886:4;883:1;876:15;902:257;974:4;968:11;;;1006:17;;-1:-1:-1;;;;;1038:34:67;;1074:22;;;1035:62;1032:88;;;1100:18;;:::i;:::-;1136:4;1129:24;902:257;:::o;1164:275::-;1235:2;1229:9;1300:2;1281:13;;-1:-1:-1;;1277:27:67;1265:40;;-1:-1:-1;;;;;1320:34:67;;1356:22;;;1317:62;1314:88;;;1382:18;;:::i;:::-;1418:2;1411:22;1164:275;;-1:-1:-1;1164:275:67:o;1444:187::-;1493:4;-1:-1:-1;;;;;1518:6:67;1515:30;1512:56;;;1548:18;;:::i;:::-;-1:-1:-1;1614:2:67;1593:15;-1:-1:-1;;1589:29:67;1620:4;1585:40;;1444:187::o;1636:464::-;1679:5;1732:3;1725:4;1717:6;1713:17;1709:27;1699:55;;1750:1;1747;1740:12;1699:55;1786:6;1773:20;1817:49;1833:32;1862:2;1833:32;:::i;:::-;1817:49;:::i;:::-;1891:2;1882:7;1875:19;1937:3;1930:4;1925:2;1917:6;1913:15;1909:26;1906:35;1903:55;;;1954:1;1951;1944:12;1903:55;2019:2;2012:4;2004:6;2000:17;1993:4;1984:7;1980:18;1967:55;2067:1;2042:16;;;2060:4;2038:27;2031:38;;;;2046:7;1636:464;-1:-1:-1;;;1636:464:67:o;2105:131::-;-1:-1:-1;;;;;2180:31:67;;2170:42;;2160:70;;2226:1;2223;2216:12;2241:678;2338:6;2346;2354;2407:2;2395:9;2386:7;2382:23;2378:32;2375:52;;;2423:1;2420;2413:12;2375:52;2463:9;2450:23;-1:-1:-1;;;;;2533:2:67;2525:6;2522:14;2519:34;;;2549:1;2546;2539:12;2519:34;2572:50;2614:7;2605:6;2594:9;2590:22;2572:50;:::i;:::-;2562:60;;2675:2;2664:9;2660:18;2647:32;2631:48;;2704:2;2694:8;2691:16;2688:36;;;2720:1;2717;2710:12;2688:36;;2743:52;2787:7;2776:8;2765:9;2761:24;2743:52;:::i;:::-;2733:62;;;2845:2;2834:9;2830:18;2817:32;2858:31;2883:5;2858:31;:::i;:::-;2908:5;2898:15;;;2241:678;;;;;:::o;2924:315::-;2992:6;3000;3053:2;3041:9;3032:7;3028:23;3024:32;3021:52;;;3069:1;3066;3059:12;3021:52;3108:9;3095:23;3127:31;3152:5;3127:31;:::i;:::-;3177:5;3229:2;3214:18;;;;3201:32;;-1:-1:-1;;;2924:315:67:o;3436:158::-;3498:5;3543:3;3534:6;3529:3;3525:16;3521:26;3518:46;;;3560:1;3557;3550:12;3518:46;-1:-1:-1;3582:6:67;3436:158;-1:-1:-1;3436:158:67:o;3599:360::-;3687:6;3740:2;3728:9;3719:7;3715:23;3711:32;3708:52;;;3756:1;3753;3746:12;3708:52;3796:9;3783:23;-1:-1:-1;;;;;3821:6:67;3818:30;3815:50;;;3861:1;3858;3851:12;3815:50;3884:69;3945:7;3936:6;3925:9;3921:22;3884:69;:::i;4118:1336::-;4038:12;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;;4060:47;4484:4;4532:3;4517:19;;4609:2;4647:3;4642:2;4631:9;4627:18;4620:31;4671:6;4706;4700:13;4737:6;4729;4722:22;4775:3;4764:9;4760:19;4753:26;;4838:3;4828:6;4825:1;4821:14;4810:9;4806:30;4802:40;4788:54;;4861:4;4900;4892:6;4888:17;4923:1;4933:429;4947:6;4944:1;4941:13;4933:429;;;5012:22;;;-1:-1:-1;;5008:37:67;4996:50;;5069:13;;5110:9;;5095:25;;5159:11;;5153:18;5191:15;;;5184:27;;;5234:48;5266:15;;;5153:18;5234:48;:::i;:::-;5224:58;-1:-1:-1;;5340:12:67;;;;5305:15;;;;4969:1;4962:9;4933:429;;;-1:-1:-1;;4038:12:67;;5444:2;5429:18;;4026:25;-1:-1:-1;;;4100:4:67;4089:16;;4083:23;4067:14;;;4060:47;-1:-1:-1;5379:6:67;-1:-1:-1;5394:54:67;3964:149;5667:154;5726:5;5771:2;5762:6;5757:3;5753:16;5749:25;5746:45;;;5787:1;5784;5777:12;5826:347;5877:8;5887:6;5941:3;5934:4;5926:6;5922:17;5918:27;5908:55;;5959:1;5956;5949:12;5908:55;-1:-1:-1;5982:20:67;;-1:-1:-1;;;;;6014:30:67;;6011:50;;;6057:1;6054;6047:12;6011:50;6094:4;6086:6;6082:17;6070:29;;6146:3;6139:4;6130:6;6122;6118:19;6114:30;6111:39;6108:59;;;6163:1;6160;6153:12;6178:1046;6319:6;6327;6335;6343;6351;6359;6367;6420:3;6408:9;6399:7;6395:23;6391:33;6388:53;;;6437:1;6434;6427:12;6388:53;6460;6505:7;6494:9;6460:53;:::i;:::-;6450:63;;6560:2;6549:9;6545:18;6532:32;6522:42;;6615:3;6604:9;6600:19;6587:33;-1:-1:-1;;;;;6680:2:67;6672:6;6669:14;6666:34;;;6696:1;6693;6686:12;6666:34;6735:58;6785:7;6776:6;6765:9;6761:22;6735:58;:::i;:::-;6812:8;;-1:-1:-1;6709:84:67;-1:-1:-1;6897:3:67;6882:19;;6869:33;;-1:-1:-1;6911:31:67;6869:33;6911:31;:::i;:::-;6961:5;;-1:-1:-1;7019:3:67;7004:19;;6991:33;;7036:16;;;7033:36;;;7065:1;7062;7055:12;7033:36;;7104:60;7156:7;7145:8;7134:9;7130:24;7104:60;:::i;:::-;6178:1046;;;;-1:-1:-1;6178:1046:67;;-1:-1:-1;6178:1046:67;;;;7078:86;;-1:-1:-1;;;6178:1046:67:o;7723:247::-;7782:6;7835:2;7823:9;7814:7;7810:23;7806:32;7803:52;;;7851:1;7848;7841:12;7803:52;7890:9;7877:23;7909:31;7934:5;7909:31;:::i;8461:456::-;8538:6;8546;8554;8607:2;8595:9;8586:7;8582:23;8578:32;8575:52;;;8623:1;8620;8613:12;8575:52;8662:9;8649:23;8681:31;8706:5;8681:31;:::i;:::-;8731:5;-1:-1:-1;8788:2:67;8773:18;;8760:32;8801:33;8760:32;8801:33;:::i;:::-;8461:456;;8853:7;;-1:-1:-1;;;8907:2:67;8892:18;;;;8879:32;;8461:456::o;9111:163::-;9178:20;;9238:10;9227:22;;9217:33;;9207:61;;9264:1;9261;9254:12;9207:61;9111:163;;;:::o;9279:184::-;9337:6;9390:2;9378:9;9369:7;9365:23;9361:32;9358:52;;;9406:1;9403;9396:12;9358:52;9429:28;9447:9;9429:28;:::i;9803:252::-;9870:6;9878;9931:2;9919:9;9910:7;9906:23;9902:32;9899:52;;;9947:1;9944;9937:12;9899:52;9970:28;9988:9;9970:28;:::i;10060:118::-;10146:5;10139:13;10132:21;10125:5;10122:32;10112:60;;10168:1;10165;10158:12;10183:489;10277:6;10285;10338:2;10326:9;10317:7;10313:23;10309:32;10306:52;;;10354:1;10351;10344:12;10306:52;10394:9;10381:23;-1:-1:-1;;;;;10419:6:67;10416:30;10413:50;;;10459:1;10456;10449:12;10413:50;10482:69;10543:7;10534:6;10523:9;10519:22;10482:69;:::i;:::-;10472:79;;;10601:2;10590:9;10586:18;10573:32;10614:28;10636:5;10614:28;:::i;:::-;10661:5;10651:15;;;10183:489;;;;;:::o;10677:253::-;4038:12;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;;4060:47;10867:2;10852:18;;10879:45;3964:149;10935:159;11002:20;;11062:6;11051:18;;11041:29;;11031:57;;11084:1;11081;11074:12;11099:184;11157:6;11210:2;11198:9;11189:7;11185:23;11181:32;11178:52;;;11226:1;11223;11216:12;11178:52;11249:28;11267:9;11249:28;:::i;11288:256::-;11354:6;11362;11415:2;11403:9;11394:7;11390:23;11386:32;11383:52;;;11431:1;11428;11421:12;11383:52;11454:28;11472:9;11454:28;:::i;:::-;11444:38;;11501:37;11534:2;11523:9;11519:18;11501:37;:::i;:::-;11491:47;;11288:256;;;;;:::o;12265:385::-;12337:6;12345;12353;12406:2;12394:9;12385:7;12381:23;12377:32;12374:52;;;12422:1;12419;12412:12;12374:52;12445:28;12463:9;12445:28;:::i;:::-;12435:38;;12492:37;12525:2;12514:9;12510:18;12492:37;:::i;:::-;12482:47;;12579:2;12568:9;12564:18;12551:32;12592:28;12614:5;12592:28;:::i;12860:668::-;12972:6;12980;12988;12996;13049:3;13037:9;13028:7;13024:23;13020:33;13017:53;;;13066:1;13063;13056:12;13017:53;13089;13134:7;13123:9;13089:53;:::i;:::-;13079:63;;13193:2;13182:9;13178:18;13165:32;-1:-1:-1;;;;;13212:6:67;13209:30;13206:50;;;13252:1;13249;13242:12;13206:50;13291:58;13341:7;13332:6;13321:9;13317:22;13291:58;:::i;:::-;13368:8;;-1:-1:-1;13265:84:67;-1:-1:-1;;13453:3:67;13438:19;;13425:33;13467:31;13425:33;13467:31;:::i;:::-;12860:668;;;;-1:-1:-1;12860:668:67;;-1:-1:-1;;12860:668:67:o;13533:395::-;13624:8;13634:6;13688:3;13681:4;13673:6;13669:17;13665:27;13655:55;;13706:1;13703;13696:12;13655:55;-1:-1:-1;13729:20:67;;-1:-1:-1;;;;;13761:30:67;;13758:50;;;13804:1;13801;13794:12;13758:50;13841:4;13833:6;13829:17;13817:29;;13901:3;13894:4;13884:6;13881:1;13877:14;13869:6;13865:27;13861:38;13858:47;13855:67;;;13918:1;13915;13908:12;13933:504;14058:6;14066;14119:2;14107:9;14098:7;14094:23;14090:32;14087:52;;;14135:1;14132;14125:12;14087:52;14175:9;14162:23;-1:-1:-1;;;;;14200:6:67;14197:30;14194:50;;;14240:1;14237;14230:12;14194:50;14279:98;14369:7;14360:6;14349:9;14345:22;14279:98;:::i;:::-;14396:8;;14253:124;;-1:-1:-1;13933:504:67;-1:-1:-1;;;;13933:504:67:o;14624:553::-;14710:6;14718;14726;14734;14787:2;14775:9;14766:7;14762:23;14758:32;14755:52;;;14803:1;14800;14793:12;14755:52;14826:28;14844:9;14826:28;:::i;:::-;14816:38;;14873:37;14906:2;14895:9;14891:18;14873:37;:::i;:::-;14863:47;;14961:2;14950:9;14946:18;14933:32;-1:-1:-1;;;;;14980:6:67;14977:30;14974:50;;;15020:1;15017;15010:12;14974:50;15059:58;15109:7;15100:6;15089:9;15085:22;15059:58;:::i;:::-;14624:553;;;;-1:-1:-1;15136:8:67;-1:-1:-1;;;;14624:553:67:o;15685:655::-;15821:6;15829;15837;15881:9;15872:7;15868:23;15911:3;15907:2;15903:12;15900:32;;;15928:1;15925;15918:12;15900:32;15968:9;15955:23;-1:-1:-1;;;;;15993:6:67;15990:30;15987:50;;;16033:1;16030;16023:12;15987:50;16056:69;16117:7;16108:6;16097:9;16093:22;16056:69;:::i;:::-;16046:79;-1:-1:-1;;16159:2:67;-1:-1:-1;;16141:16:67;;16137:25;16134:45;;;16175:1;16172;16165:12;16134:45;;16213:2;16202:9;16198:18;16188:28;;16266:2;16255:9;16251:18;16238:32;16279:31;16304:5;16279:31;:::i;16345:609::-;16585:4;16627:3;16616:9;16612:19;16604:27;;16664:6;16658:13;16647:9;16640:32;-1:-1:-1;;;;;16732:4:67;16724:6;16720:17;16714:24;16710:49;16703:4;16692:9;16688:20;16681:79;16807:4;16799:6;16795:17;16789:24;16822:62;16878:4;16867:9;16863:20;16849:12;4038;;4026:25;;4100:4;4089:16;;;4083:23;4067:14;;4060:47;3964:149;16822:62;-1:-1:-1;4038:12:67;;16943:3;16928:19;;4026:25;4100:4;4089:16;;4083:23;4067:14;;;4060:47;16893:55;3964:149;16959:388;17027:6;17035;17088:2;17076:9;17067:7;17063:23;17059:32;17056:52;;;17104:1;17101;17094:12;17056:52;17143:9;17130:23;17162:31;17187:5;17162:31;:::i;:::-;17212:5;-1:-1:-1;17269:2:67;17254:18;;17241:32;17282:33;17241:32;17282:33;:::i;17352:234::-;17435:6;17488:2;17476:9;17467:7;17463:23;17459:32;17456:52;;;17504:1;17501;17494:12;17456:52;17527:53;17572:7;17561:9;17527:53;:::i;17591:380::-;17670:1;17666:12;;;;17713;;;17734:61;;17788:4;17780:6;17776:17;17766:27;;17734:61;17841:2;17833:6;17830:14;17810:18;17807:38;17804:161;;17887:10;17882:3;17878:20;17875:1;17868:31;17922:4;17919:1;17912:15;17950:4;17947:1;17940:15;18458:127;18519:10;18514:3;18510:20;18507:1;18500:31;18550:4;18547:1;18540:15;18574:4;18571:1;18564:15;18590:168;18663:9;;;18694;;18711:15;;;18705:22;;18691:37;18681:71;;18732:18;;:::i;18763:217::-;18803:1;18829;18819:132;;18873:10;18868:3;18864:20;18861:1;18854:31;18908:4;18905:1;18898:15;18936:4;18933:1;18926:15;18819:132;-1:-1:-1;18965:9:67;;18763:217::o;19689:127::-;19750:10;19745:3;19741:20;19738:1;19731:31;19781:4;19778:1;19771:15;19805:4;19802:1;19795:15;19821:336;19926:4;19984:11;19971:25;20078:2;20074:7;20063:8;20047:14;20043:29;20039:43;20019:18;20015:68;20005:96;;20097:1;20094;20087:12;20005:96;20118:33;;;;;19821:336;-1:-1:-1;;19821:336:67:o;20162:521::-;20239:4;20245:6;20305:11;20292:25;20399:2;20395:7;20384:8;20368:14;20364:29;20360:43;20340:18;20336:68;20326:96;;20418:1;20415;20408:12;20326:96;20445:33;;20497:20;;;-1:-1:-1;;;;;;20529:30:67;;20526:50;;;20572:1;20569;20562:12;20526:50;20605:4;20593:17;;-1:-1:-1;20636:14:67;20632:27;;;20622:38;;20619:58;;;20673:1;20670;20663:12;20813:542;20914:2;20909:3;20906:11;20903:446;;;20950:1;20974:5;20971:1;20964:16;21018:4;21015:1;21005:18;21088:2;21076:10;21072:19;21069:1;21065:27;21059:4;21055:38;21124:4;21112:10;21109:20;21106:47;;;-1:-1:-1;21147:4:67;21106:47;21202:2;21197:3;21193:12;21190:1;21186:20;21180:4;21176:31;21166:41;;21257:82;21275:2;21268:5;21265:13;21257:82;;;21320:17;;;21301:1;21290:13;21257:82;;;21261:3;;;20813:542;;;:::o;21531:1202::-;-1:-1:-1;;;;;21648:3:67;21645:27;21642:53;;;21675:18;;:::i;:::-;21704:93;21793:3;21753:38;21785:4;21779:11;21753:38;:::i;:::-;21747:4;21704:93;:::i;:::-;21823:1;21848:2;21843:3;21840:11;21865:1;21860:615;;;;22519:1;22536:3;22533:93;;;-1:-1:-1;22592:19:67;;;22579:33;22533:93;-1:-1:-1;;21488:1:67;21484:11;;;21480:24;21476:29;21466:40;21512:1;21508:11;;;21463:57;22639:78;;21833:894;;21860:615;20760:1;20753:14;;;20797:4;20784:18;;-1:-1:-1;;21896:17:67;;;21996:9;22018:229;22032:7;22029:1;22026:14;22018:229;;;22121:19;;;22108:33;22093:49;;22228:4;22213:20;;;;22181:1;22169:14;;;;22048:12;22018:229;;;22022:3;22275;22266:7;22263:16;22260:159;;;22399:1;22395:6;22389:3;22383;22380:1;22376:11;22372:21;22368:34;22364:39;22351:9;22346:3;22342:19;22329:33;22325:79;22317:6;22310:95;22260:159;;;22462:1;22456:3;22453:1;22449:11;22445:19;22439:4;22432:33;21833:894;;21531:1202;;;:::o;22738:266::-;22826:6;22821:3;22814:19;22878:6;22871:5;22864:4;22859:3;22855:14;22842:43;-1:-1:-1;22930:1:67;22905:16;;;22923:4;22901:27;;;22894:38;;;;22986:2;22965:15;;;-1:-1:-1;;22961:29:67;22952:39;;;22948:50;;22738:266::o;23009:1774::-;23266:2;23318:21;;;23291:18;;;23374:22;;;23237:4;;23415:2;23433:18;;;23497:1;23493:14;;;23478:30;;23474:39;;23536:6;23237:4;23570:1184;23584:6;23581:1;23578:13;23570:1184;;;23649:22;;;-1:-1:-1;;23645:36:67;23633:49;;23721:20;;23796:14;23792:27;;;-1:-1:-1;;23788:41:67;23764:66;;23754:94;;23844:1;23841;23834:12;23754:94;23874:31;;23928:4;23990:10;23964:24;23874:31;23964:24;:::i;:::-;23960:41;23952:6;23945:57;24078:6;24043:33;24072:2;24065:5;24061:14;24043:33;:::i;:::-;24039:46;24034:2;24026:6;24022:15;24015:71;24151:2;24144:5;24140:14;24127:28;24240:2;24236:7;24228:5;24212:14;24208:26;24204:40;24182:20;24178:67;24168:95;;24259:1;24256;24249:12;24168:95;24291:32;;;24399:16;;;;-1:-1:-1;24350:21:67;-1:-1:-1;;;;;24431:30:67;;24428:50;;;24474:1;24471;24464:12;24428:50;24527:6;24511:14;24507:27;24498:7;24494:41;24491:61;;;24548:1;24545;24538:12;24491:61;24589:2;24584;24576:6;24572:15;24565:27;24615:59;24670:2;24662:6;24658:15;24650:6;24641:7;24615:59;:::i;:::-;24732:12;;;;24605:69;-1:-1:-1;;;24697:15:67;;;;-1:-1:-1;23606:1:67;23599:9;23570:1184;;;-1:-1:-1;24771:6:67;;23009:1774;-1:-1:-1;;;;;;;;23009:1774:67:o;24788:331::-;24893:9;24904;24946:8;24934:10;24931:24;24928:44;;;24968:1;24965;24958:12;24928:44;24997:6;24987:8;24984:20;24981:40;;;25017:1;25014;25007:12;24981:40;-1:-1:-1;;25043:23:67;;;25088:25;;;;;-1:-1:-1;24788:331:67:o;25124:476::-;25315:3;25353:6;25347:13;25369:66;25428:6;25423:3;25416:4;25408:6;25404:17;25369:66;:::i;:::-;25457:16;;25510:6;25502;25457:16;25482:35;25574:1;25536:18;;25563:13;;;-1:-1:-1;25536:18:67;;25124:476;-1:-1:-1;;;25124:476:67:o;25605:244::-;25762:2;25751:9;25744:21;25725:4;25782:61;25839:2;25828:9;25824:18;25816:6;25808;25782:61;:::i;25854:331::-;25953:4;26011:11;25998:25;26105:3;26101:8;26090;26074:14;26070:29;26066:44;26046:18;26042:69;26032:97;;26125:1;26122;26115:12;26190:129;-1:-1:-1;;;;;26268:5:67;26264:30;26257:5;26254:41;26244:69;;26309:1;26306;26299:12;26324:988;26698:10;26671:25;26689:6;26671:25;:::i;:::-;26667:42;26656:9;26649:61;26773:4;26765:6;26761:17;26748:31;26741:4;26730:9;26726:20;26719:61;26630:4;26827;26819:6;26815:17;26802:31;26842:30;26866:5;26842:30;:::i;:::-;-1:-1:-1;;;;;26914:5:67;26910:30;26903:4;26892:9;26888:20;26881:60;;26977:6;26972:2;26961:9;26957:18;26950:34;27021:3;27015;27004:9;27000:19;26993:32;27048:62;27105:3;27094:9;27090:19;27082:6;27074;27048:62;:::i;:::-;-1:-1:-1;;;;;27147:32:67;;27167:3;27126:19;;27119:61;27217:22;;;27211:3;27196:19;;27189:51;27257:49;27221:6;27291;27283;27257:49;:::i;:::-;27249:57;26324:988;-1:-1:-1;;;;;;;;;;26324:988:67:o;27317:648::-;27396:6;27449:2;27437:9;27428:7;27424:23;27420:32;27417:52;;;27465:1;27462;27455:12;27417:52;27498:9;27492:16;-1:-1:-1;;;;;27523:6:67;27520:30;27517:50;;;27563:1;27560;27553:12;27517:50;27586:22;;27639:4;27631:13;;27627:27;-1:-1:-1;27617:55:67;;27668:1;27665;27658:12;27617:55;27697:2;27691:9;27722:49;27738:32;27767:2;27738:32;:::i;27722:49::-;27794:2;27787:5;27780:17;27834:7;27829:2;27824;27820;27816:11;27812:20;27809:33;27806:53;;;27855:1;27852;27845:12;27806:53;27868:67;27932:2;27927;27920:5;27916:14;27911:2;27907;27903:11;27868:67;:::i;28768:245::-;28826:6;28879:2;28867:9;28858:7;28854:23;28850:32;28847:52;;;28895:1;28892;28885:12;28847:52;28934:9;28921:23;28953:30;28977:5;28953:30;:::i;29018:479::-;29285:1;29281;29276:3;29272:11;29268:19;29260:6;29256:32;29245:9;29238:51;29325:6;29320:2;29309:9;29305:18;29298:34;29380:6;29372;29368:19;29363:2;29352:9;29348:18;29341:47;29424:3;29419:2;29408:9;29404:18;29397:31;29219:4;29445:46;29486:3;29475:9;29471:19;29463:6;29445:46;:::i;30120:379::-;30313:2;30302:9;30295:21;30276:4;30339:45;30380:2;30369:9;30365:18;30357:6;30339:45;:::i;:::-;30432:9;30424:6;30420:22;30415:2;30404:9;30400:18;30393:50;30460:33;30486:6;30478;30460:33;:::i;30504:245::-;30571:6;30624:2;30612:9;30603:7;30599:23;30595:32;30592:52;;;30640:1;30637;30630:12;30592:52;30672:9;30666:16;30691:28;30713:5;30691:28;:::i;30754:887::-;30973:2;30962:9;30955:21;31031:10;31022:6;31016:13;31012:30;31007:2;30996:9;30992:18;30985:58;31097:4;31089:6;31085:17;31079:24;31074:2;31063:9;31059:18;31052:52;30936:4;31151:2;31143:6;31139:15;31133:22;31192:4;31186:3;31175:9;31171:19;31164:33;31220:52;31267:3;31256:9;31252:19;31238:12;31220:52;:::i;:::-;31206:66;;31321:2;31313:6;31309:15;31303:22;31395:2;31391:7;31379:9;31371:6;31367:22;31363:36;31356:4;31345:9;31341:20;31334:66;31423:41;31457:6;31441:14;31423:41;:::i;:::-;31533:3;31521:16;;;;31515:23;31508:31;31501:39;31495:3;31480:19;;31473:68;-1:-1:-1;;;;;;;;31602:32:67;;;;31595:4;31580:20;;;31573:62;31409:55;30754:887::o;31646:284::-;31716:5;31764:4;31752:9;31747:3;31743:19;31739:30;31736:50;;;31782:1;31779;31772:12;31736:50;31804:22;;:::i;:::-;31795:31;;31855:9;31849:16;31842:5;31835:31;31919:2;31908:9;31904:18;31898:25;31893:2;31886:5;31882:14;31875:49;31646:284;;;;:::o;31935:257::-;32033:6;32086:2;32074:9;32065:7;32061:23;32057:32;32054:52;;;32102:1;32099;32092:12;32054:52;32125:61;32178:7;32167:9;32125:61;:::i;32197:318::-;-1:-1:-1;;;;;;32317:19:67;;32388:11;;;;32419:1;32411:10;;32408:101;;;32496:2;32490;32483:3;32480:1;32476:11;32473:1;32469:19;32465:28;32461:2;32457:37;32453:46;32444:55;;32408:101;;;32197:318;;;;:::o;32520:346::-;32607:6;32660:2;32648:9;32639:7;32635:23;32631:32;32628:52;;;32676:1;32673;32666:12;32628:52;32702:22;;:::i;:::-;32760:9;32747:23;32740:5;32733:38;32831:2;32820:9;32816:18;32803:32;32798:2;32791:5;32787:14;32780:56;32855:5;32845:15;;;32520:346;;;;:::o;33210:255::-;33330:19;;33369:2;33361:11;;33358:101;;;-1:-1:-1;;33430:2:67;33426:12;;;33423:1;33419:20;33415:33;33404:45;33210:255;;;;:::o;33470:331::-;-1:-1:-1;;;;;;33590:19:67;;33674:11;;;;33705:1;33697:10;;33694:101;;;33766:1;33762:11;;;;33759:1;33755:19;33751:28;;;33743:37;33739:46;;;;33470:331;-1:-1:-1;;33470:331:67:o;33806:568::-;-1:-1:-1;;;;;34071:3:67;34067:28;34058:6;34053:3;34049:16;34045:51;34040:3;34033:64;34157:10;34152:3;34148:20;34139:6;34134:3;34130:16;34126:43;34122:1;34117:3;34113:11;34106:64;34200:6;34195:2;34190:3;34186:12;34179:28;34015:3;34236:6;34230:13;34252:75;34320:6;34315:2;34310:3;34306:12;34299:4;34291:6;34287:17;34252:75;:::i;:::-;34347:16;;;;34365:2;34343:25;;33806:568;-1:-1:-1;;;;;33806:568:67:o;34379:135::-;34418:3;34439:17;;;34436:43;;34459:18;;:::i;:::-;-1:-1:-1;34506:1:67;34495:13;;34379:135::o;35138:532::-;35379:6;35374:3;35367:19;-1:-1:-1;;;;;35442:3:67;35438:28;35429:6;35424:3;35420:16;35416:51;35411:2;35406:3;35402:12;35395:73;35498:6;35493:2;35488:3;35484:12;35477:28;35349:3;35534:6;35528:13;35550:73;35616:6;35611:2;35606:3;35602:12;35597:2;35589:6;35585:15;35550:73;:::i;:::-;35643:16;;;;35661:2;35639:25;;35138:532;-1:-1:-1;;;;;35138:532:67:o;36094:128::-;36161:9;;;36182:11;;;36179:37;;;36196:18;;:::i;36227:681::-;36329:6;36382:3;36370:9;36361:7;36357:23;36353:33;36350:53;;;36399:1;36396;36389:12;36350:53;36432:2;36426:9;36474:4;36466:6;36462:17;36545:6;36533:10;36530:22;-1:-1:-1;;;;;36497:10:67;36494:34;36491:62;36488:88;;;36556:18;;:::i;:::-;36592:2;36585:22;36631:16;;36616:32;;36691:2;36676:18;;36670:25;36704:30;36670:25;36704:30;:::i;:::-;36762:2;36750:15;;36743:30;36806:70;36868:7;36863:2;36848:18;;36806:70;:::i;:::-;36801:2;36789:15;;36782:95;36793:6;36227:681;-1:-1:-1;;;36227:681:67:o;36913:1343::-;37039:3;37033:10;-1:-1:-1;;;;;37058:6:67;37055:30;37052:56;;;37088:18;;:::i;:::-;37117:96;37206:6;37166:38;37198:4;37192:11;37166:38;:::i;:::-;37160:4;37117:96;:::i;:::-;37268:4;;37325:2;37314:14;;37342:1;37337:662;;;;38043:1;38060:6;38057:89;;;-1:-1:-1;38112:19:67;;;38106:26;38057:89;-1:-1:-1;;21488:1:67;21484:11;;;21480:24;21476:29;21466:40;21512:1;21508:11;;;21463:57;38159:81;;37307:943;;37337:662;20760:1;20753:14;;;20797:4;20784:18;;-1:-1:-1;;37373:20:67;;;37490:236;37504:7;37501:1;37498:14;37490:236;;;37593:19;;;37587:26;37572:42;;37685:27;;;;37653:1;37641:14;;;;37520:19;;37490:236;;;37494:3;37754:6;37745:7;37742:19;37739:201;;;37815:19;;;37809:26;-1:-1:-1;;37898:1:67;37894:14;;;37910:3;37890:24;37886:37;37882:42;37867:58;37852:74;;37739:201;-1:-1:-1;;;;;37986:1:67;37970:14;;;37966:22;37953:36;;-1:-1:-1;36913:1343:67:o;38261:125::-;38326:9;;;38347:10;;;38344:36;;;38360:18;;:::i;38391:251::-;38461:6;38514:2;38502:9;38493:7;38489:23;38485:32;38482:52;;;38530:1;38527;38520:12;38482:52;38562:9;38556:16;38581:31;38606:5;38581:31;:::i
Swarm Source
ipfs://031524f18b86ada60e42e02fdc1e3f7577c3b607cb28a16400194b8b5d17c0a1
Loading...
Loading
Loading...
Loading

Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.