creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-v5/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 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"
      },
      "@openzeppelin/contracts-v5/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\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"
      },
      "@openzeppelin/contracts-v5/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 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    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 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        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\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        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\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    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    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    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts-v5/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol": {
        "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n    event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n    function feeTo() external view returns (address);\n    function feeToSetter() external view returns (address);\n\n    function getPair(address tokenA, address tokenB) external view returns (address pair);\n    function allPairs(uint) external view returns (address pair);\n    function allPairsLength() external view returns (uint);\n\n    function createPair(address tokenA, address tokenB) external returns (address pair);\n\n    function setFeeTo(address) external;\n    function setFeeToSetter(address) external;\n}\n"
      },
      "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol": {
        "content": "pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n    function factory() external pure returns (address);\n    function WETH() external pure returns (address);\n\n    function addLiquidity(\n        address tokenA,\n        address tokenB,\n        uint amountADesired,\n        uint amountBDesired,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB, uint liquidity);\n    function addLiquidityETH(\n        address token,\n        uint amountTokenDesired,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n    function removeLiquidity(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETH(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountToken, uint amountETH);\n    function removeLiquidityWithPermit(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETHWithPermit(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountToken, uint amountETH);\n    function swapExactTokensForTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapTokensForExactTokens(\n        uint amountOut,\n        uint amountInMax,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n\n    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n"
      },
      "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol": {
        "content": "pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n    function removeLiquidityETHSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountETH);\n    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountETH);\n\n    function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n    function swapExactETHForTokensSupportingFeeOnTransferTokens(\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external payable;\n    function swapExactTokensForETHSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n}\n"
      },
      "@uniswap/v2-periphery/contracts/interfaces/IWETH.sol": {
        "content": "pragma solidity >=0.5.0;\n\ninterface IWETH {\n    function deposit() external payable;\n    function transfer(address to, uint value) external returns (bool);\n    function withdraw(uint) external;\n}\n"
      },
      "contracts/erc20/deploy/IMetadropERC20.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"@openzeppelin/contracts-v5/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts-v5/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IMetadropERC20 is IERC20, IERC20Metadata {\n  error LimitCannotBeChanged();\n  error LimitMustBeHigherOrUnchanged();\n  error InitialLiquidityNotYetAdded();\n  error TransferFailed();\n  error MaxTokensPerWalletExceeded();\n  error IncorrectETHValueProvided();\n  error DeductionsOnBuyExceedOrEqualOneHundredPercent();\n  error AutoswapThresholdTooLow();\n  error TotalSupplyNotMinted();\n  error RecipientsAndAmountsMismatch();\n  error CannotPerformDuringAutoswap();\n  error NoETHForLiquidityPair();\n  error InitialLiquidityAlreadyAdded();\n  error InsufficientTokensForInitialLiquidity();\n  error LPTokensBalanceMismatch();\n  error LiquidityPoolCannotBeAddressZero();\n  error CanOnlyReduce();\n  error MaxBuysPerBlockExceeded();\n  error MaxTokensPerTransactionExceeded();\n  error CannotWithdrawThisToken();\n  error AmountExceedsAvailable();\n  error PlatformFeeAlreadyDistributed();\n\n  event AutoswapThresholdUpdated(uint256 oldThreshold, uint256 newThreshold);\n  event ExternalCallError(uint256 identifier);\n  event InitialLiquidityAdded(uint256 tokenA, uint256 tokenB, uint256 lpToken);\n\n  event MaxTokensPerWalletLimitUpdated(uint256 previousLimit, uint256 newLimit);\n  event MaxTokensPerTransactionLimitUpdated(\n    uint256 previousLimit,\n    uint256 newLimit\n  );\n  event LiquidityLocked(\n    uint256 lpTokens,\n    uint256 lpLockupInDays,\n    uint256 streamId\n  );\n  event LiquidityBurned(uint256 lpTokens);\n  event LiquidityPoolCreated(address addedPool);\n  event LiquidityPoolAddressUpdated(address account, bool isLiquidityPool);\n  event TaxExemptAddressUpdated(address account, bool isTaxExempt);\n  event MetadropTaxBasisPointsChanged(\n    uint256 oldBuyBasisPoints,\n    uint256 newBuyBasisPoints,\n    uint256 oldSellBasisPoints,\n    uint256 newSellBasisPoints\n  );\n  event ProjectTaxBasisPointsChanged(\n    uint256 oldBuyBasisPoints,\n    uint256 newBuyBasisPoints,\n    uint256 oldSellBasisPoints,\n    uint256 newSellBasisPoints\n  );\n  event ProjectTaxRecipientUpdated(address treasury);\n  event UnlimitedAddressUpdated(address account, bool isUnlimited);\n  event PlatformFeeDistributed();\n\n  struct ERC20BaseParams {\n    string name;\n    string symbol;\n    address metadropTreasury;\n    address initialOwner;\n    address uniswapV2Router;\n    address tokenVault;\n    uint256 totalSupply;\n    address[] supplyRecipients;\n    uint256[] supplyAmounts;\n  }\n\n  struct ERC20LiquidityParams {\n    bool burnLPTokens;\n    address lpOwner;\n    uint256 ethAmountForLP;\n    uint256 lpLockupInDays;\n  }\n\n  struct ERC20AutoburnParams {\n    uint256 autoburnDurationInBlocks;\n    uint256 autoburnBasisPoints;\n  }\n\n  struct ERC20LaunchPoolParams {\n    address launchPoolFactory;\n    uint256 launchPoolSupply;\n  }\n\n  struct ERC20LimitParams {\n    uint256 limitProtectionDurationInSeconds;\n    uint256 maxTokensPerTransaction;\n    uint256 maxTokensPerWallet;\n  }\n\n  struct ERC20TaxParams {\n    uint256 projectBuyTaxBasisPoints;\n    uint256 projectSellTaxBasisPoints;\n    uint256 autoswapThresholdBasisPoints;\n    uint256 metadropBuyTaxBasisPoints;\n    uint256 metadropSellTaxBasisPoints;\n    uint256 metadropTaxPeriodInDays;\n    address projectTaxRecipient;\n    address metadropTaxRecipient;\n    uint256 metadropMinBuyTaxBasisPoints;\n    uint256 metadropMinSellTaxBasisPoints;\n    uint256 metadropBuyTaxProportionBasisPoints;\n    uint256 metadropSellTaxProportionBasisPoints;\n  }\n\n  function addInitialLiquidity(\n    uint256 lpLockupInDaysOverride_,\n    bool burnLPTokensOverride_\n  ) external payable;\n  function isLiquidityPool(address address_) external view returns (bool);\n  function isUnlimited(address address_) external view returns (bool);\n  function isTaxExempt(address address_) external view returns (bool);\n  function setIsLiquidityPool(address address_, bool isLiquidityPool_) external;\n  function setIsUnlimited(address address_, bool isUnlimited_) external;\n  function setIsTaxExempt(address address_, bool isTaxExempt_) external;\n  function setProjectTaxRecipient(address projectTaxRecipient_) external;\n  function setAutoswapThresholdBasisPoints(\n    uint256 swapThresholdBasisPoints_\n  ) external;\n  function setProjectTaxRates(\n    uint256 newProjectBuyTaxBasisPoints_,\n    uint256 newProjectSellTaxBasisPoints_\n  ) external;\n  function setLimits(\n    uint256 newMaxTokensPerTransaction_,\n    uint256 newMaxTokensPerWallet_\n  ) external;\n  function limitsEnforced() external view returns (bool);\n  function getMetadropBuyTaxBasisPoints() external view returns (uint256);\n  function getMetadropSellTaxBasisPoints() external view returns (uint256);\n  function totalBuyTaxBasisPoints() external view returns (uint256);\n  function totalSellTaxBasisPoints() external view returns (uint256);\n  function burn(uint256 value) external;\n  function burnFrom(address account, uint256 value) external;\n\n  function tokenSupplyForLP() external returns (uint256);\n  function limitProtectionDurationInSeconds() external returns (uint256);\n  function metadropTaxPeriodInDays() external returns (uint256);\n  function metadropBuyTaxProportionBasisPoints() external returns (uint256);\n  function metadropSellTaxProportionBasisPoints() external returns (uint256);\n  function metadropMinBuyTaxBasisPoints() external returns (uint256);\n  function metadropMinSellTaxBasisPoints() external returns (uint256);\n  function autoburnDurationInBlocks() external returns (uint256);\n  function autoburnBasisPoints() external returns (uint256);\n  function metadropTaxRecipient() external returns (address);\n  function uniswapV2Pair() external returns (address);\n  // function launchPool() external returns (address);\n  function lpOwner() external returns (address);\n  function distributePlatformFee() external;\n}\n"
      },
      "contracts/lib/IErrors.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.24;\n\ninterface IErrors {\n  enum BondingCurveErrorType {\n    OK, //                                                  No error\n    INVALID_NUMITEMS, //                                    The numItem value is 0\n    SPOT_PRICE_OVERFLOW //                                  The updated spot price doesn't fit into 128 bits\n  }\n\n  error AdapterParamsMustBeEmpty(); //                      The adapter parameters on this LZ call must be empty.\n\n  error AdditionToPoolIsBelowPerTransactionMinimum(); //    The contribution amount is less than the minimum.\n\n  error AdditionToPoolWouldExceedPoolCap(); //              This addition to the pool would exceed the pool cap.\n\n  error AdditionToPoolWouldExceedPerAddressCap(); //        This addition to the pool would exceed the per address cap.\n\n  error AddressAlreadySet(); //                             The address being set can only be set once, and is already non-0.\n\n  error AllowanceDecreasedBelowZero(); //                   You cannot decrease the allowance below zero.\n\n  error AlreadyInitialised(); //                            The contract is already initialised: it cannot be initialised twice!\n\n  error AmountExceedsAvailable(); //                        You are requesting more token than is available.\n\n  error ApprovalCallerNotOwnerNorApproved(); //             The caller must own the token or be an approved operator.\n\n  error ApproveFromTheZeroAddress(); //                     Approval cannot be called from the zero address (indeed, how have you??).\n\n  error ApproveToTheZeroAddress(); //                       Approval cannot be given to the zero address.\n\n  error ApprovalQueryForNonexistentToken(); //              The token does not exist.\n\n  error AuctionStatusIsNotEnded(); //                       Throw if the action required the auction to be closed, and it isn't.\n\n  error AuctionStatusIsNotOpen(); //                        Throw if the action requires the auction to be open, and it isn't.\n\n  error AuxCallFailed(\n    address[] modules,\n    uint256 value,\n    bytes data,\n    uint256 txGas\n  ); //                                                     An auxilliary call from the drop factory failed.\n\n  error BalanceMismatch(); //                               An error when comparing balance amounts.\n\n  error BalanceQueryForZeroAddress(); //                    Cannot query the balance for the zero address.\n\n  error BidMustBeBelowTheFloorWhenReducingQuantity(); //    Only bids that are below the floor can reduce the quantity of the bid.\n\n  error BidMustBeBelowTheFloorForRefundDuringAuction(); //  Only bids that are below the floor can be refunded during the auction.\n\n  error BondingCurveError(BondingCurveErrorType error); //  An error of the type specified has occured in bonding curve processing.\n\n  error botProtectionDurationInSecondsMustFitUint128(); //  botProtectionDurationInSeconds cannot be too large.\n\n  error BurnExceedsBalance(); //                            The amount you have selected to burn exceeds the addresses balance.\n\n  error BurnFromTheZeroAddress(); //                        Tokens cannot be burned from the zero address. (Also, how have you called this!?!)\n\n  error CallerIsNotDepositBoxOwner(); //                    The caller is not the owner of the deposit box.\n\n  error CallerIsNotFactory(); //                            The caller of this function must match the factory address in storage.\n\n  error CallerIsNotFactoryOrProjectOwner(); //              The caller of this function must match the factory address OR project owner address.\n\n  error CallerIsNotFactoryProjectOwnerOrPool(); //          The caller of this function must match the factory address, project owner or pool address.\n\n  error CallerIsNotTheFeeRecipient(); //                    The caller is not the fee recipient.\n\n  error CallerIsNotTheOwner(); //                           The caller is not the owner of this contract.\n\n  error CallerIsNotTheManager(); //                         The caller is not the manager of this contract.\n\n  error CallerMustBeLzApp(); //                             The caller must be an LZ application.\n\n  error CallerIsNotPlatformAdmin(address caller); //        The caller of this function must be part of the platformAdmin group.\n\n  error CallerIsNotSuperAdmin(address caller); //           The caller of this function must match the superAdmin address in storage.\n\n  error CannotAddLiquidityOnCreateAndUseDRIPool(); //       Cannot use both liquidity added on create and a DRIPool in the same token.\n\n  error CannotManuallyFundLPWhenUsingADRIPool(); //         Cannot add liquidity manually when using a DRI pool.\n\n  error CannotPerformDuringAutoswap(); //                   Cannot call this function during an autoswap.\n\n  error CannotSetNewOwnerToTheZeroAddress(); //             You can't set the owner of this contract to the zero address (address(0)).\n\n  error CannotSetToZeroAddress(); //                        The corresponding address cannot be set to the zero address (address(0)).\n\n  error CannotSetNewManagerToTheZeroAddress(); //           Cannot transfer the manager to the zero address (address(0)).\n\n  error CannotWithdrawThisToken(); //                       Cannot withdraw the specified token.\n\n  error CanOnlyReduce(); //                                 The given operation can only reduce the value specified.\n\n  error CollectionAlreadyRevealed(); //                     The collection is already revealed; you cannot call reveal again.\n\n  error ContractIsDecommissioned(); //                      This contract is decommissioned!\n\n  error ContractIsPaused(); //                              The call requires the contract to be unpaused, and it is paused.\n\n  error ContractIsNotPaused(); //                           The call required the contract to be paused, and it is NOT paused.\n\n  error DecreasedAllowanceBelowZero(); //                   The request would decrease the allowance below zero, and that is not allowed.\n\n  error DestinationIsNotTrustedSource(); //                 The destination that is being called through LZ has not been set as trusted.\n\n  error DeductionsOnBuyExceedOrEqualOneHundredPercent(); // The total of all buy deductions cannot equal or exceed 100%.\n\n  error DeployerOnly(); //                                  This method can only be called by the deployer address.\n\n  error DeploymentError(); //                               Error on deployment.\n\n  error DepositBoxIsNotOpen(); //                           This action cannot complete as the deposit box is not open.\n\n  error DriPoolAddressCannotBeAddressZero(); //             The Dri Pool address cannot be the zero address.\n\n  error GasLimitIsTooLow(); //                              The gas limit for the LayerZero call is too low.\n\n  error IncorrectConfirmationValue(); //                    You need to enter the right confirmation value to call this funtion (usually 69420).\n\n  error IncorrectPayment(); //                              The function call did not include passing the correct payment.\n\n  error InitialLiquidityAlreadyAdded(); //                  Initial liquidity has already been added. You can't do it again.\n\n  error InitialLiquidityNotYetAdded(); //                   Initial liquidity needs to have been added for this to succedd.\n\n  error InsufficientAllowance(); //                         There is not a high enough allowance for this operation.\n\n  error InvalidAdapterParams(); //                          The current adapter params for LayerZero on this contract won't work :(.\n\n  error InvalidAddress(); //                                An address being processed in the function is not valid.\n\n  error InvalidEndpointCaller(); //                         The calling address is not a valid LZ endpoint. The LZ endpoint was set at contract creation\n  //                                                        and cannot be altered after. Check the address LZ endpoint address on the contract.\n\n  error InvalidHash(); //                                   The passed hash does not meet requirements.\n\n  error InvalidMinGas(); //                                 The minimum gas setting for LZ in invalid.\n\n  error InvalidOracleSignature(); //                        The signature provided with the contract call is not valid, either in format or signer.\n\n  error InvalidPayload(); //                                The LZ payload is invalid\n\n  error InvalidReceiver(); //                               The address used as a target for funds is not valid.\n\n  error InvalidSourceSendingContract(); //                  The LZ message is being related from a source contract on another chain that is NOT trusted.\n\n  error InvalidTotalShares(); //                            Total shares must equal 100 percent in basis points.\n\n  error LimitsCanOnlyBeRaised(); //                         Limits are UP ONLY.\n\n  error LimitTooHigh(); //                                  The limit has been set too high.\n\n  error ListLengthMismatch(); //                            Two or more lists were compared and they did not match length.\n\n  error LiquidityPoolMustBeAContractAddress(); //           Cannot add a non-contract as a liquidity pool.\n\n  error LiquidityPoolCannotBeAddressZero(); //              Cannot add a liquidity pool from the zero address.\n\n  error LPLockUpMustFitUint88(); //                         LP lockup is held in a uint88, so must fit.\n\n  error NoTrustedPathRecord(); //                           LZ needs a trusted path record for this to work. What's that, you ask?\n\n  error MachineAddressCannotBeAddressZero(); //             Cannot set the machine address to the zero address.\n\n  error ManagerUnauthorizedAccount(); //                    The caller is not the pending manager.\n\n  error MaxBidQuantityIs255(); //                           Validation: as we use a uint8 array to track bid positions the max bid quantity is 255.\n\n  error MaxBuysPerBlockExceeded(); //                       You have exceeded the max buys per block.\n\n  error MaxPublicMintAllowanceExceeded(\n    uint256 requested,\n    uint256 alreadyMinted,\n    uint256 maxAllowance\n  ); //                                                     The calling address has requested a quantity that would exceed the max allowance.\n\n  error TotalSupplyTooHigh(); //                              Max supply must fit in a uint128.\n\n  error MaxTokensPerWalletExceeded(); //                    The transfer would exceed the max tokens per wallet limit.\n\n  error MaxTokensPerTransactionExceeded(); //                       The transfer would exceed the max tokens per transaction limit.\n\n  error MetadataIsLocked(); //                              The metadata on this contract is locked; it cannot be altered!\n\n  error MetadropFactoryOnlyOncePerReveal(); //              This function can only be called (a) by the factory and, (b) just one time!\n\n  error MetadropModulesOnly(); //                           Can only be called from a metadrop contract.\n\n  error MetadropOracleCannotBeAddressZero(); //             The metadrop Oracle cannot be the zero address (address(0)).\n\n  error MinETHCannotExceedMaxBuy(); //                      The min ETH amount cannot exceed the max buy amount.\n\n  error MinETHCannotExceedMaxLiquidity(); //                The min ETH amount cannot exceed the max liquidity amount.\n\n  error MinGasLimitNotSet(); //                             The minimum gas limit for LayerZero has not been set.\n\n  error MintERC2309QuantityExceedsLimit(); //               The `quantity` minted with ERC2309 exceeds the safety limit.\n\n  error MintingIsClosedForever(); //                        Minting is, as the error suggests, so over (and locked forever).\n\n  error MintToZeroAddress(); //                             Cannot mint to the zero address.\n\n  error MintZeroQuantity(); //                              The quantity of tokens minted must be more than zero.\n\n  error NewBuyTaxBasisPointsExceedsMaximum(); //            Project owner trying to set the tax rate too high.\n\n  error NewSellTaxBasisPointsExceedsMaximum(); //           Project owner trying to set the tax rate too high.\n\n  error NoETHForLiquidityPair(); //                         No ETH has been provided for the liquidity pair.\n\n  error TaxPeriodStillInForce(); //                         The minimum tax period has not yet expired.\n\n  error NoPaymentDue(); //                                  No payment is due for this address.\n\n  error NoRefundForCaller(); //                             Error thrown when the calling address has no refund owed.\n\n  error NoStoredMessage(); //                               There is no stored message matching the passed parameters.\n\n  error NothingToClaim(); //                                The calling address has nothing to claim.\n\n  error InsufficientTokensForInitialLiquidity(); //                       There is no token to add to the LP.\n\n  error OperationDidNotSucceed(); //                        The operation failed (vague much?).\n\n  error OracleSignatureHasExpired(); //                     A signature has been provided but it is too old.\n\n  error OwnershipNotInitializedForExtraData(); //           The `extraData` cannot be set on an uninitialized ownership slot.\n\n  error OwnerQueryForNonexistentToken(); //                 The token does not exist.\n\n  error ParametersDoNotMatchSignedMessage(); //             The parameters passed with the signed message do not match the message itself.\n\n  error ParamTooLargeStartDate(); //                        The passed parameter exceeds the var type max.\n\n  error ParamTooLargeEndDate(); //                          The passed parameter exceeds the var type max.\n\n  error ParamTooLargeMinETH(); //                           The passed parameter exceeds the var type max.\n\n  error ParamTooLargePerAddressMax(); //                    The passed parameter exceeds the var type max.\n\n  error ParamTooLargeVestingDays(); //                      The passed parameter exceeds the var type max.\n\n  error ParamTooLargePoolSupply(); //                       The passed parameter exceeds the var type max.\n\n  error ParamTooLargePoolMaxETH(); //                       The passed parameter exceeds the var type max.\n\n  error ParamTooLargePoolPerTxnMinETH(); //                 The passed parameter exceeds the var type max.\n\n  error ParamTooLargeContributionFee(); //                  The passed parameter exceeds the var type max.\n\n  error ParamTooLargeMaxInitialBuy(); //                    The passed parameter exceeds the var type max.\n\n  error ParamTooLargeMaxInitialLiquidity(); //              The passed parameter exceeds the var type max.\n\n  error PassedConfigDoesNotMatchApproved(); //              The config provided on the call does not match the approved config.\n\n  error PauseCutOffHasPassed(); //                          The time period in which we can pause has passed; this contract can no longer be paused.\n\n  error PaymentMustCoverPerMintFee(); //                    The payment passed must at least cover the per mint fee for the quantity requested.\n\n  error PermitDidNotSucceed(); //                           The safeERC20 permit failed.\n\n  error PlatformAdminCannotBeAddressZero(); //              We cannot use the zero address (address(0)) as a platformAdmin.\n\n  error PlatformTreasuryCannotBeAddressZero(); //           The treasury address cannot be set to the zero address.\n\n  error PoolCannotBeManuallyStarted(); //                   This pool cannot be manually started.\n\n  error PoolIsAboveMinimum(); //                            You required the pool to be below the minimum, and it is not\n\n  error PoolIsBelowMinimum(); //                            You required the pool to be above the minimum, and it is not\n\n  error PoolMustBeSeededWithETHForInitialLiquidity(); //    You must pass ETH for liquidity with this type of pool.\n\n  error AlreadyInitialized(); //                            The contract is already initialized.\n\n  error LiquidityPoolAlreadyCreated(); //                   The liquidity pool has already been created.\n\n  error PoolPhaseIsNotOpen(); //                            The block.timestamp is either before the pool is open or after it is closed.\n\n  error PoolPhaseIsNotFailed(); //                          The pool status must be failed.\n\n  error PoolPhaseIsNotSucceeded(); //                       The pool status must be succeeded.\n\n  error PoolVestingNotYetComplete(); //                     Tokens in the pool are not yet vested.\n\n  error ProjectOwnerCannotBeAddressZero(); //               The project owner has to be a non zero address.\n\n  error ProofInvalid(); //                                  The provided proof is not valid with the provided arguments.\n\n  error QuantityExceedsRemainingCollectionSupply(); //      The requested quantity would breach the collection supply.\n\n  error QuantityExceedsRemainingPhaseSupply(); //           The requested quantity would breach the phase supply.\n\n  error QuantityExceedsMaxPossibleCollectionSupply(); //    The requested quantity would breach the maximum trackable supply\n\n  error RecipientsAndAmountsMismatch(); //                  The number of recipients and amounts do not match.\n\n  error ReferralIdAlreadyUsed(); //                         This referral ID has already been used; they are one use only.\n\n  error RequestingMoreThanAvailableBalance(); //             The request exceeds the available balance.\n\n  error RequestingMoreThanRemainingAllocation(\n    uint256 previouslyMinted,\n    uint256 requested,\n    uint256 remainingAllocation\n  ); //                                                     Number of tokens requested for this mint exceeds the remaining allocation (taking the\n  //                                                        original allocation from the list and deducting minted tokens).\n\n  error RouterCannotBeZeroAddress(); //                     The router address cannot be Zero.\n\n  error RoyaltyFeeWillExceedSalePrice(); //                 The ERC2981 royalty specified will exceed the sale price.\n\n  error ShareTotalCannotBeZero(); //                        The total of all the shares cannot be nothing.\n\n  error SliceOutOfBounds(); //                              The bytes slice operation was out of bounds.\n\n  error SliceOverflow(); //                                 The bytes slice operation overlowed.\n\n  error SuperAdminCannotBeAddressZero(); //                 The superAdmin cannot be the sero address (address(0)).\n\n  error TotalSupplyNotMinted(); //                           The sum of the team supply and lp supply does not match.\n\n  error SupportWindowIsNotOpen(); //                        The project owner has not requested support within the support request expiry window.\n\n  error AutoswapThresholdTooLow(); // The select swap threshold is below the minimum.\n\n  error TaxFreeAddressCannotBeAddressZero(); //             A tax free address cannot be address(0)\n\n  error TemplateCannotBeAddressZero(); //                   The address for a template cannot be address zero (address(0)).\n\n  error TemplateNotFound(); //                              There is no template that matches the passed template Id.\n\n  error ThisMintIsClosed(); //                              It's over (well, this mint is, anyway).\n\n  error TotalSharesMustMatchDenominator(); //               The total of all shares must equal the denominator value.\n\n  error TransferAmountExceedsBalance(); //                  The transfer amount exceeds the accounts available balance.\n\n  error TransferCallerNotOwnerNorApproved(); //             The caller must own the token or be an approved operator.\n\n  error TransferFailed(); //                                The transfer has failed.\n\n  error TransferFromIncorrectOwner(); //                    The token must be owned by `from`.\n\n  error TransferToNonERC721ReceiverImplementer(); //        Cannot safely transfer to a contract that does not implement the ERC721Receiver interface.\n\n  error TransferFromZeroAddress(); //                       Cannot transfer from the zero address. Indeed, this surely is impossible, and likely a waste to check??\n\n  error TransferToZeroAddress(); //                         Cannot transfer to the zero address.\n\n  error UnrecognisedVRFMode(); //                           Currently supported VRF modes are 0: chainlink and 1: arrng\n\n  error UnrecognisedType(); //                              Pool type not found.\n\n  error URIQueryForNonexistentToken(); //                   The token does not exist.\n\n  error ValueExceedsMaximum(); //                           The value sent exceeds the maximum allowed (super useful explanation huh?).\n\n  error VRFCoordinatorCannotBeAddressZero(); //             The VRF coordinator cannot be the zero address (address(0)).\n\n  error VestedBalanceExceedsTotalBalance(); //              The vested balance cannot exceed the total balance.\n\n  error LPTokensBalanceMismatch(); //                       The balace of LP tokens is not as expected.\n\n  error IncorrectETHValueProvided();\n}\n"
      },
      "contracts/lib/MetadropERC20Library.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.24;\n\n// OpenZeppelin\nimport {IERC20} from \"@openzeppelin/contracts-v5/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts-v5/token/ERC20/utils/SafeERC20.sol\";\n\n// Metadrop\nimport {IErrors} from \"../lib/IErrors.sol\";\nimport {IMetadropERC20} from \"../erc20/deploy/IMetadropERC20.sol\";\n\n// Uniswap\nimport {IUniswapV2Router02} from \"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\";\nimport {IUniswapV2Factory} from \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol\";\nimport {IWETH} from \"@uniswap/v2-periphery/contracts/interfaces/IWETH.sol\";\n\n// Sablier\nimport {ISablierV2LockupLinear, LockupLinear} from \"../vendor/sablier/ISablierV2LockupLinear.sol\";\n\n\nlibrary MetadropERC20Library {\n  using SafeERC20 for IERC20;\n\n  function createWithDurations(\n    address lpOwner_,\n    address uniswapV2PairAddress_,\n    address tokenVault_,\n    uint256 lpTokenAmount_,\n    uint40 lpTokenLockupDuration_\n  ) external returns (uint256 streamId) {\n    // Setup lock Params.\n    LockupLinear.CreateWithDurations memory params;\n    // The sender will be able to cancel the stream\n    params.sender = msg.sender;\n    // The recipient of the streamed assets\n    params.recipient = lpOwner_;\n    // Total amount is the amount inclusive of all fees.\n    params.totalAmount = uint128(lpTokenAmount_);\n    // The streaming asset. Sablier requires casting as IERC20 from OZ v4.\n    params.asset = IERC20(uniswapV2PairAddress_);\n    // Whether the stream will be cancelable or not.\n    params.cancelable = false;\n    params.durations = LockupLinear.Durations({\n      // Cliff duration (must be less than total duration or will revert).\n      cliff: lpTokenLockupDuration_ - 1,\n      // Total duration.\n      total: lpTokenLockupDuration_\n    });\n    // Optional parameter for charging a variable fee.\n    // params.broker = Broker(address(0), ud(0));\n\n    // Create the LockupLinear stream using a function that sets the start time to `block.timestamp`\n    streamId = ISablierV2LockupLinear(tokenVault_).createWithDurations(params);\n  }\n\n}\n"
      },
      "contracts/vendor/sablier/ISablierV2LockupLinear.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity >=0.8.19;\n\n// Must be OpenZeppelin contracts v4.x.x\nimport {IERC20} from \"@openzeppelin/contracts-v5/token/ERC20/IERC20.sol\";\n\ntype UD60x18 is uint256;\n\nstruct Broker {\n  address account;\n  UD60x18 fee;\n}\n\nlibrary LockupLinear {\n  struct CreateWithDurations {\n    address sender;\n    address recipient;\n    uint128 totalAmount;\n    IERC20 asset;\n    bool cancelable;\n    bool transferable;\n    Durations durations;\n    Broker broker;\n  }\n\n  /// @notice Struct encapsulating the cliff duration and the total duration.\n  /// @param cliff The cliff duration in seconds.\n  /// @param total The total duration in seconds.\n  struct Durations {\n    uint40 cliff;\n    uint40 total;\n  }\n}\n\ninterface ISablierV2LockupLinear {\n  function createWithDurations(\n    LockupLinear.CreateWithDurations calldata params\n  ) external returns (uint256 streamId);\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}