{"message":"OK","result":[{"AdditionalSources":[{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n","Filename":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        if (!_safeTransfer(token, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        if (!_safeTransferFrom(token, from, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _safeTransfer(token, to, value, false);\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _safeTransferFrom(token, from, to, value, false);\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        if (!_safeApprove(token, spender, value, false)) {\n            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));\n            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the\n     * return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.transfer.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(to, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return\n     * value: the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param from The sender of the tokens\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value,\n        bool bubble\n    ) private returns (bool success) {\n        bytes4 selector = IERC20.transferFrom.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(from, shr(96, not(0))))\n            mstore(0x24, and(to, shr(96, not(0))))\n            mstore(0x44, value)\n            success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n            mstore(0x60, 0)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:\n     * the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param spender The spender of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.approve.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(spender, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/access/Ownable.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This extension of the {Ownable} contract includes a two-step mechanism to transfer\n * ownership, where the new owner must call {acceptOwnership} in order to replace the\n * old one. This can help prevent common mistakes, such as transfers of ownership to\n * incorrect accounts, or to contracts that are unable to interact with the\n * permission system.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     *\n     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n","Filename":"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n","Filename":"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n","Filename":"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n","Filename":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/utils/Context.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    bool private _paused;\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/utils/Pausable.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n    using StorageSlot for bytes32;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev A `view` only version of {nonReentrant}. Use to block view functions\n     * from being called, preventing reading from inconsistent contract state.\n     *\n     * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n     * status. Use it only on view functions. For payable or non-payable functions,\n     * use the standard {nonReentrant} modifier instead.\n     */\n    modifier nonReentrantView() {\n        _nonReentrantBeforeView();\n        _;\n    }\n\n    function _nonReentrantBeforeView() private view {\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        _nonReentrantBeforeView();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n    }\n\n    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n        return REENTRANCY_GUARD_STORAGE;\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n","Filename":"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol"},{"SourceCode":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n","Filename":"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"},{"SourceCode":"// SPDX-License-Identifier: BUSL-1.1\n// Copyright (c) 2026 long.xyz. All rights reserved.\npragma solidity ^0.8.26;\n\n/// @notice Minimal Airlock interface required by the ticker-guarded wrapper.\ninterface IAirlock {\n    struct CreateParams {\n        uint256 initialSupply;\n        uint256 numTokensToSell;\n        address numeraire;\n        address tokenFactory;\n        bytes tokenFactoryData;\n        address governanceFactory;\n        bytes governanceFactoryData;\n        address poolInitializer;\n        bytes poolInitializerData;\n        address liquidityMigrator;\n        bytes liquidityMigratorData;\n        address integrator;\n        bytes32 salt;\n    }\n\n    function create(CreateParams calldata createData)\n        external\n        returns (address asset, address pool, address governance, address timelock, address migrationPool);\n}\n","Filename":"src/interfaces/IAirlock.sol"}],"CompilerSettings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["forge-std/=lib/forge-std/src/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"viaIR":false},"ConstructorArguments":"0x000000000000000000000000eb7c034704ef8dcd2d32324c1545f62fb4ad08620000000000000000000000001b37d3a72082029c44b35b604ea473617580b69a0000000000000000000000009b7f0d4dcf6a4baed39b2f4f5aeae6ca082bed47","OptimizationRuns":200,"IsProxy":"false","SourceCode":"// SPDX-License-Identifier: BUSL-1.1\n// Copyright (c) 2026 long.xyz. All rights reserved.\n\n/*=====================================================================================================\n *\n *   _       ___    _   _    ____      _          _      _   _   _   _    ____   _   _   _____   ____\n *  | |     / _ \\  | \\ | |  / ___|    | |        / \\    | | | | | \\ | |  / ___| | | | | | ____| |  _ \\\n *  | |    | | | | |  \\| | | |  _     | |       / _ \\   | | | | |  \\| | | |     | |_| | |  _|   | |_) |\n *  | |___ | |_| | | |\\  | | |_| |    | |___   / ___ \\  | |_| | | |\\  | | |___  |  _  | | |___  |  _ <\n *  |_____| \\___/  |_| \\_|  \\____|    |_____| /_/   \\_\\  \\___/  |_| \\_|  \\____| |_| |_| |_____| |_| \\_\\\n *\n *                    T O K E N I Z E D   S T O C K S   / /   O N C H A I N\n *\n *          [ AIRLOCK ROUTER ]------[ 24H TICKER LOCK ]------[ ROBINHOOD CHAIN ]\n *\n *      PRICE\n *        ^         |             |                        /\\\n *        |    |   -+-       |   -+-        /\\      /\\    /  \\          /\\\n *        |   -+-   |       -+-   |    ____/  \\____/  \\__/    \\________/  \\____>\n *        |    |             |\n *        +---------------------------------------------------------------------------------> TIME\n *\n *                                           P L A Y\n *\n *        L            .--------.    .--------.        N   N      GGG\n *        L           /          \\__/          \\       NN  N     G\n *        L           \\          /  \\          /       N N N     G  GG\n *        LLLLL        '--------'    '--------'        N  NN      GGG\n *\n *                                  T E R M   G A M E S .\n *\n *====================================================================================================*/\n\npragma solidity ^0.8.26;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Pausable} from \"@openzeppelin/contracts/utils/Pausable.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\nimport {IAirlock} from \"./interfaces/IAirlock.sol\";\n\n/// @title LongLauncher\n/// @author @natan_benish\n/// @notice Airlock-compatible launch router that reserves normalized token tickers for 24 hours.\ncontract LongLauncher is Ownable2Step, Pausable, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n\n    /// @dev Timestamp-based wall-clock duration; independent of Robinhood's ~100 ms block cadence.\n    uint48 public constant RESERVATION_DURATION = 24 hours;\n    uint256 internal constant DOPPLER_ERC20_V1_TOKEN_DATA_HEAD_SIZE = 11 * 32;\n    uint256 internal constant MAX_TICKER_LENGTH = 15;\n\n    IAirlock public immutable AIRLOCK;\n    address public immutable TRUSTED_TOKEN_FACTORY;\n\n    struct TickerRecord {\n        address token;\n        uint48 deployedAt;\n        uint48 reservedUntil;\n    }\n\n    mapping(bytes32 tickerKey => TickerRecord record) private _records;\n\n    error ZeroAddress();\n    error UnsupportedTokenFactory(address supplied, address expected);\n    error MalformedTokenData();\n    error InvalidTickerLength(uint256 length);\n    error InvalidTickerCharacter(uint256 index, bytes1 character);\n    error TickerReserved(bytes32 tickerKey, address token, uint48 reservedUntil);\n    error DeployedSymbolMismatch(bytes32 submittedKey, bytes32 deployedKey);\n    error TimestampOverflow();\n    error NativeTransferFailed();\n    error OwnershipRenunciationDisabled();\n\n    event LaunchCreated(\n        address indexed poolOrHook,\n        address indexed asset,\n        address indexed numeraire,\n        address poolInitializer,\n        address launcher,\n        bytes32 tickerKey,\n        uint48 deployedAt,\n        uint48 reservedUntil,\n        string normalizedTicker\n    );\n    event NativeSwept(address indexed recipient, uint256 amount);\n    event ERC20Swept(address indexed token, address indexed recipient, uint256 amount);\n\n    constructor(address airlock_, address trustedTokenFactory_, address initialOwner) Ownable(initialOwner) {\n        if (airlock_ == address(0) || trustedTokenFactory_ == address(0)) revert ZeroAddress();\n        AIRLOCK = IAirlock(airlock_);\n        TRUSTED_TOKEN_FACTORY = trustedTokenFactory_;\n    }\n\n    receive() external payable {}\n\n    /// @notice Forwards an unchanged Airlock create request after enforcing ticker availability.\n    function create(IAirlock.CreateParams calldata data)\n        external\n        whenNotPaused\n        nonReentrant\n        returns (address asset, address pool, address governance, address timelock, address migrationPool)\n    {\n        if (data.tokenFactory != TRUSTED_TOKEN_FACTORY) {\n            revert UnsupportedTokenFactory(data.tokenFactory, TRUSTED_TOKEN_FACTORY);\n        }\n\n        (bytes32 key, string memory normalizedTicker) = _tickerFromTokenFactoryData(data.tokenFactoryData);\n        TickerRecord memory current = _records[key];\n        if (block.timestamp < current.reservedUntil) {\n            revert TickerReserved(key, current.token, current.reservedUntil);\n        }\n\n        (asset, pool, governance, timelock, migrationPool) = AIRLOCK.create(data);\n\n        _registerSuccessfulLaunch(data, asset, pool, key, normalizedTicker, msg.sender);\n    }\n\n    function tickerKey(string calldata ticker) external pure returns (bytes32 key) {\n        (key,) = _normalizeTicker(bytes(ticker));\n    }\n\n    function getTickerRecord(string calldata ticker) external view returns (TickerRecord memory) {\n        (bytes32 key,) = _normalizeTicker(bytes(ticker));\n        return _records[key];\n    }\n\n    function isTickerAvailable(string calldata ticker) external view returns (bool) {\n        (bytes32 key,) = _normalizeTicker(bytes(ticker));\n        return block.timestamp >= _records[key].reservedUntil;\n    }\n\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    function sweepNative(address payable recipient, uint256 amount) external onlyOwner nonReentrant {\n        if (recipient == address(0)) revert ZeroAddress();\n        (bool success,) = recipient.call{value: amount}(\"\");\n        if (!success) revert NativeTransferFailed();\n        emit NativeSwept(recipient, amount);\n    }\n\n    function sweepERC20(address token, address recipient, uint256 amount) external onlyOwner nonReentrant {\n        if (token == address(0) || recipient == address(0)) revert ZeroAddress();\n        IERC20(token).safeTransfer(recipient, amount);\n        emit ERC20Swept(token, recipient, amount);\n    }\n\n    function renounceOwnership() public pure override {\n        revert OwnershipRenunciationDisabled();\n    }\n\n    function _registerSuccessfulLaunch(\n        IAirlock.CreateParams calldata data,\n        address asset,\n        address pool,\n        bytes32 key,\n        string memory normalizedTicker,\n        address launcher\n    ) internal {\n        (bytes32 deployedKey,) = _normalizeTicker(bytes(IERC20Metadata(asset).symbol()));\n        if (deployedKey != key) revert DeployedSymbolMismatch(key, deployedKey);\n\n        uint256 reservedUntil256 = block.timestamp + RESERVATION_DURATION;\n        if (reservedUntil256 > type(uint48).max) revert TimestampOverflow();\n\n        uint48 deployedAt = uint48(block.timestamp);\n        uint48 reservedUntil = uint48(reservedUntil256);\n        _records[key] = TickerRecord({token: asset, deployedAt: deployedAt, reservedUntil: reservedUntil});\n\n        emit LaunchCreated(\n            pool,\n            asset,\n            data.numeraire,\n            data.poolInitializer,\n            launcher,\n            key,\n            deployedAt,\n            reservedUntil,\n            normalizedTicker\n        );\n    }\n\n    /// @dev The V1 payload is abi.encode(name, symbol, schedules, beneficiaries, scheduleIds,\n    /// amounts, tokenURI, maxBalanceLimit, balanceLimitEnd, controller, exclusions).\n    function _tickerFromTokenFactoryData(bytes calldata tokenData)\n        internal\n        pure\n        returns (bytes32 key, string memory normalizedTicker)\n    {\n        if (tokenData.length < DOPPLER_ERC20_V1_TOKEN_DATA_HEAD_SIZE) revert MalformedTokenData();\n\n        uint256 symbolOffset;\n        assembly (\"memory-safe\") {\n            symbolOffset := calldataload(add(tokenData.offset, 0x20))\n        }\n\n        if (\n            symbolOffset < DOPPLER_ERC20_V1_TOKEN_DATA_HEAD_SIZE || symbolOffset & 31 != 0\n                || symbolOffset > tokenData.length - 32\n        ) {\n            revert MalformedTokenData();\n        }\n\n        uint256 length;\n        assembly (\"memory-safe\") {\n            length := calldataload(add(tokenData.offset, symbolOffset))\n        }\n\n        uint256 contentOffset = symbolOffset + 32;\n        if (contentOffset > tokenData.length || length > tokenData.length - contentOffset) {\n            revert MalformedTokenData();\n        }\n        if (length == 0 || length > MAX_TICKER_LENGTH) revert InvalidTickerLength(length);\n\n        bytes memory ticker = new bytes(length);\n        assembly (\"memory-safe\") {\n            calldatacopy(add(ticker, 0x20), add(tokenData.offset, contentOffset), length)\n        }\n        return _normalizeTicker(ticker);\n    }\n\n    function _normalizeTicker(bytes memory ticker)\n        internal\n        pure\n        returns (bytes32 key, string memory normalizedTicker)\n    {\n        uint256 length = ticker.length;\n        if (length == 0 || length > MAX_TICKER_LENGTH) revert InvalidTickerLength(length);\n\n        for (uint256 i; i < length; ++i) {\n            uint8 character = uint8(ticker[i]);\n            if (character >= 97 && character <= 122) {\n                ticker[i] = bytes1(character - 32);\n            } else if (character < 65 || character > 90) {\n                revert InvalidTickerCharacter(i, ticker[i]);\n            }\n        }\n\n        key = keccak256(ticker);\n        normalizedTicker = string(ticker);\n    }\n}\n","ABI":"[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"airlock_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"trustedTokenFactory_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initialOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"submittedKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"deployedKey\",\"type\":\"bytes32\"}],\"name\":\"DeployedSymbolMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EnforcedPause\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExpectedPause\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"bytes1\",\"name\":\"character\",\"type\":\"bytes1\"}],\"name\":\"InvalidTickerCharacter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidTickerLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MalformedTokenData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeTransferFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnershipRenunciationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"tickerKey\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint48\",\"name\":\"reservedUntil\",\"type\":\"uint48\"}],\"name\":\"TickerReserved\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TimestampOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"supplied\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expected\",\"type\":\"address\"}],\"name\":\"UnsupportedTokenFactory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ERC20Swept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"poolOrHook\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"numeraire\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"poolInitializer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"launcher\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"tickerKey\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint48\",\"name\":\"deployedAt\",\"type\":\"uint48\"},{\"indexed\":false,\"internalType\":\"uint48\",\"name\":\"reservedUntil\",\"type\":\"uint48\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"normalizedTicker\",\"type\":\"string\"}],\"name\":\"LaunchCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeSwept\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"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\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"AIRLOCK\",\"outputs\":[{\"internalType\":\"contract IAirlock\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RESERVATION_DURATION\",\"outputs\":[{\"internalType\":\"uint48\",\"name\":\"\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TRUSTED_TOKEN_FACTORY\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numTokensToSell\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"numeraire\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenFactory\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"tokenFactoryData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"governanceFactory\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"governanceFactoryData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"poolInitializer\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"poolInitializerData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"liquidityMigrator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"liquidityMigratorData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"integrator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"}],\"internalType\":\"struct IAirlock.CreateParams\",\"name\":\"data\",\"type\":\"tuple\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governance\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"timelock\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"migrationPool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"ticker\",\"type\":\"string\"}],\"name\":\"getTickerRecord\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint48\",\"name\":\"deployedAt\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"reservedUntil\",\"type\":\"uint48\"}],\"internalType\":\"struct LongLauncher.TickerRecord\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"ticker\",\"type\":\"string\"}],\"name\":\"isTickerAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"sweepNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"ticker\",\"type\":\"string\"}],\"name\":\"tickerKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]","ContractName":"LongLauncher","CompilerVersion":"v0.8.26+commit.8a97fa7a","OptimizationUsed":"true","EVMVersion":"cancun","FileName":"src/LongLauncher.sol","Address":"0x22e99278308b393ea1260859b181ad7e78f5eeed"}],"status":"1"}