creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// solhint-disable-next-line interface-starts-with-i\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  function getRoundData(\n    uint80 _roundId\n  ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n  function latestRoundData()\n    external\n    view\n    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// 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"
      },
      "@openzeppelin/contracts/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/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/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/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"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// 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"
      },
      "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS\n    }\n\n    /**\n     * @dev The signature derives the `address(0)`.\n     */\n    error ECDSAInvalidSignature();\n\n    /**\n     * @dev The signature has an invalid length.\n     */\n    error ECDSAInvalidSignatureLength(uint256 length);\n\n    /**\n     * @dev The signature has an S value that is in the upper half order.\n     */\n    error ECDSAInvalidSignatureS(bytes32 s);\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n     * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n     * and a bytes32 providing additional information about the error.\n     *\n     * If no error is returned, then the address can be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {\n        unchecked {\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            return tryRecover(hash, v, r, s);\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError, bytes32) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS, s);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature, bytes32(0));\n        }\n\n        return (signer, RecoverError.NoError, bytes32(0));\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n     */\n    function _throwError(RecoverError error, bytes32 errorArg) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert ECDSAInvalidSignature();\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert ECDSAInvalidSignatureLength(uint256(errorArg));\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert ECDSAInvalidSignatureS(errorArg);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing a bytes32 `messageHash` with\n     * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n     * keccak256, although any bytes32 value can be safely used because the final digest will\n     * be re-hashed.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing an arbitrary `message` with\n     * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n        return\n            keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x00` (data with intended validator).\n     *\n     * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n     * `validator` address. Then hashing the result.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).\n     *\n     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n     * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, hex\"19_01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            digest := keccak256(ptr, 0x42)\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\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 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 */\nabstract contract ReentrancyGuard {\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    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = 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    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = 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        _status = 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 _status == ENTERED;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "contracts/Common.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @notice Thrown when updating an address with zero address\nerror ZeroAddress();\n\n/// @notice Thrown when updating with an array of no values\nerror ZeroLengthArray();\n\n/// @notice Thrown when updating with the same value as previously stored\nerror IdenticalValue();\n\n/// @notice Thrown when two array lengths does not match\nerror ArrayLengthMismatch();\n\n/// @notice Thrown when sign is invalid\nerror InvalidSignature();\n\n/// @dev The address of the Ethereum\nIERC20 constant ETH = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);"
      },
      "contracts/IPreSale.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IRounds } from \"./IRounds.sol\";\n\ninterface IPreSale is IRounds {\n    /// @notice Purchases token with claim amount\n    /// @param token The purchase token\n    /// @param tokenPrice The current price of token in 10 decimals\n    /// @param referenceNormalizationFactor The value to handle decimals\n    /// @param amount The purchase amount\n    /// @param minAmountToken The minimum amount of token recipient will get\n    /// @param recipient The address of the recipient\n    /// @param round The round in which user will purchase\n    function purchaseWithClaim(\n        IERC20 token,\n        uint256 tokenPrice,\n        uint8 referenceNormalizationFactor,\n        uint256 amount,\n        uint256 minAmountToken,\n        address recipient,\n        uint32 round\n    ) external payable;\n}"
      },
      "contracts/IRounds.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\ninterface IRounds {\n    /// @notice Returns the round details of the round\n    function rounds(uint32 round) external view returns (uint256 startTime, uint256 endTime, uint256 price);\n}"
      },
      "contracts/PreSale.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ECDSA } from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport { MessageHashUtils } from \"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\nimport { Rounds, Ownable } from \"./Rounds.sol\";\nimport { IPreSale } from \"./IPreSale.sol\";\n\nimport \"./Common.sol\";\n\n/// @title PreSale contract\n/// @notice Implements preSale of the token\n/// @dev The presale contract allows you to purchase presale token with allowed tokens,\n/// and there will be certain rounds\n\ncontract PreSale is IPreSale, Rounds, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    using Address for address payable;\n\n    /// @notice Thrown when address is blacklisted\n    error Blacklisted();\n\n    /// @notice Thrown when buy is disabled\n    error BuyNotEnable();\n\n    /// @notice Thrown when sign deadline is expired\n    error DeadlineExpired();\n\n    /// @notice Thrown when Eth price suddenly drops while purchasing tokens\n    error UnexpectedPriceDifference();\n\n    /// @notice Thrown when value to transfer is zero\n    error ZeroValue();\n\n    /// @notice Thrown when price from price feed returns zero\n    error PriceNotFound();\n\n    /// @notice Thrown when caller is not claims contract\n    error OnlyClaims();\n\n    /// @notice Thrown when purchase amount is less than required\n    error InvalidPurchase();\n\n    /// @notice Thrown when both price feed and reference price are non zero\n    error CodeSyncIssue();\n\n    /// @notice Thrown if the price is not updated\n    error PriceNotUpdated();\n\n    /// @notice Thrown if the roundId of price is not updated\n    error RoundIdNotUpdated();\n\n    /// @notice Thrown when max cap is reached\n    error MaxCapReached();\n\n    /// @notice That buyEnable or not\n    bool public buyEnable = true;\n\n    /// @notice The address of signer wallet\n    address public signerWallet;\n\n    /// @notice The address of claims contract\n    address public claimsContract;\n\n    /// @notice The address of funds wallet\n    address public fundsWallet;\n\n    /// @notice The maximum number of tokens that will be sold in presale\n    uint256 public immutable maxCap;\n\n    /// @notice Sum of tokens purchased in presale\n    uint256 public totalPurchases;\n\n    /// @notice To achieve return value of required decimals while calculation\n    uint256 private constant NORMALIZARION_FACTOR = 1e30;\n\n    /// @notice Gives claim info of user in every round\n    mapping(address => mapping(uint32 => uint256)) public claims;\n\n    /// @notice Gives info about address's permission\n    mapping(address => bool) public blacklistAddress;\n\n    /// @member price The price of token from price feed\n    /// @member normalizationFactorForToken The normalization factor to achieve return value of 18 decimals ,while calculating token purchases and always with different token decimals\n    struct TokenInfo {\n        uint256 latestPrice;\n        uint8 normalizationFactorForToken;\n    }\n\n    /// @dev Emitted when token is purchased with ETH\n    event PurchasedWithETH(\n        address indexed by,\n        string code,\n        uint256 amountPurchasedETH,\n        uint32 indexed round,\n        uint256 indexed roundPrice,\n        uint256 tokenPurchased\n    );\n\n    /// @dev Emitted when presale tokens are purchased with any token\n    event PurchasedWithToken(\n        IERC20 indexed token,\n        uint256 tokenPrice,\n        address indexed by,\n        string code,\n        uint256 amountPurchased,\n        uint256 tokenPurchased,\n        uint32 indexed round\n    );\n\n    /// @dev Emitted when tokens are purchased with claim amount\n    event PurchasedWithClaimAmount(\n        address indexed by,\n        uint256 amount,\n        IERC20 token,\n        uint32 indexed round,\n        uint256 indexed tokenPrice,\n        uint256 tokenPurchased\n    );\n\n    /// @dev Emitted when address of signer is updated\n    event SignerUpdated(address oldSigner, address newSigner);\n\n    /// @dev Emitted when address of funds wallet is updated\n    event FundsWalletUpdated(address oldAddress, address newAddress);\n\n    /// @dev Emitted when blacklist access of address is updated\n    event BlacklistUpdated(address which, bool accessNow);\n\n    /// @dev Emitted when buying access changes\n    event BuyEnableUpdated(bool oldAccess, bool newAccess);\n\n    /// @notice Restricts when updating wallet/contract address with zero address\n    modifier checkAddressZero(address which) {\n        if (which == address(0)) {\n            revert ZeroAddress();\n        }\n        _;\n    }\n\n    /// @notice Ensures that buy is enabled when buying\n    modifier canBuy() {\n        if (!buyEnable) {\n            revert BuyNotEnable();\n        }\n        _;\n    }\n\n    /// @dev Constructor\n    /// @param fundsWalletAddress The address of funds wallet\n    /// @param signerAddress The address of signer wallet\n    /// @param claimsContractAddress The address of claim contract\n    /// @param owner The address of owner wallet\n    /// @param lastRound The last round created\n    /// @param initMaxCap The max cap of bluemoon token\n    constructor(\n        address fundsWalletAddress,\n        address signerAddress,\n        address claimsContractAddress,\n        address owner,\n        uint32 lastRound,\n        uint256 initMaxCap\n    ) Rounds(lastRound) Ownable(owner) {\n        if (fundsWalletAddress == address(0) || signerAddress == address(0) || claimsContractAddress == address(0)) {\n            revert ZeroAddress();\n        }\n        fundsWallet = fundsWalletAddress;\n        signerWallet = signerAddress;\n        claimsContract = claimsContractAddress;\n        \n        _checkValue(initMaxCap);\n        maxCap = initMaxCap;\n    }\n\n    /// @notice The Chainlink inherited function, give us tokens live price\n    function getLatestPrice(IERC20 token) public view returns (TokenInfo memory) {\n        PriceFeedData memory data = tokenData[token];\n        TokenInfo memory tokenInfo;\n        if (address(data.priceFeed) == address(0)) {\n            return tokenInfo;\n        }\n        (\n            uint80 roundId,\n            /*uint80 roundID*/ int price /*uint256 startedAt*/ /*uint80 answeredInRound*/,\n            ,\n            uint256 updatedAt,\n\n        ) = /*uint256 timeStamp*/ data.priceFeed.latestRoundData();\n        if (roundId == 0) {\n            revert RoundIdNotUpdated();\n        }\n        if (updatedAt == 0 || block.timestamp - updatedAt > data.tolerance) {\n            revert PriceNotUpdated();\n        }\n        return\n            TokenInfo({\n                latestPrice: uint256(price),\n                normalizationFactorForToken: data.normalizationFactorForToken\n            });\n    }\n\n    /// @notice Changes access of buying\n    /// @param enabled The decision about buying\n    function enableBuy(bool enabled) external onlyOwner {\n        if (buyEnable == enabled) {\n            revert IdenticalValue();\n        }\n        emit BuyEnableUpdated({ oldAccess: buyEnable, newAccess: enabled });\n        buyEnable = enabled;\n    }\n\n    /// @notice Changes signer wallet address\n    /// @param newSigner The address of the new signer wallet\n    function changeSigner(address newSigner) external checkAddressZero(newSigner) onlyOwner {\n        address oldSigner = signerWallet;\n        if (oldSigner == newSigner) {\n            revert IdenticalValue();\n        }\n        emit SignerUpdated({ oldSigner: oldSigner, newSigner: newSigner });\n        signerWallet = newSigner;\n    }\n\n    /// @notice Changes funds wallet to a new address\n    /// @param newFundsWallet The address of the new funds wallet\n    function changeFundsWallet(address newFundsWallet) external checkAddressZero(newFundsWallet) onlyOwner {\n        address oldWallet = fundsWallet;\n        if (oldWallet == newFundsWallet) {\n            revert IdenticalValue();\n        }\n        emit FundsWalletUpdated({ oldAddress: oldWallet, newAddress: newFundsWallet });\n        fundsWallet = newFundsWallet;\n    }\n\n    /// @notice Changes the access of any address in contract interaction\n    /// @param which The address for which access is updated\n    /// @param access The access decision of `which` address\n    function updateBlackListedUser(address which, bool access) external checkAddressZero(which) onlyOwner {\n        bool oldAccess = blacklistAddress[which];\n        if (oldAccess == access) {\n            revert IdenticalValue();\n        }\n        emit BlacklistUpdated({ which: which, accessNow: access });\n        blacklistAddress[which] = access;\n    }\n\n    /// @notice Purchases presale token with ETH\n    /// @param code The code is used to verify signature of the user\n    /// @param round The round in which user wants to purchase\n    /// @param deadline The deadline is validity of the signature\n    /// @param minAmountToken The minAmountToken user agrees to purchase\n    /// @param v The `v` signature parameter\n    /// @param r The `r` signature parameter\n    /// @param s The `s` signature parameter\n    function purchaseTokenWithETH(\n        string memory code,\n        uint32 round,\n        uint256 deadline,\n        uint256 minAmountToken,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external payable nonReentrant canBuy {\n        // The input must have been signed by the presale signer\n        _validatePurchaseWithETH(msg.value, round, deadline, code, v, r, s);\n        uint256 roundPrice = _getRoundPriceForToken(round, ETH);\n        TokenInfo memory tokenInfo = getLatestPrice(ETH);\n        if (tokenInfo.latestPrice == 0) {\n            revert PriceNotFound();\n        }\n        uint256 toReturn = _calculateAndUpdateTokenAmount(\n            msg.value,\n            tokenInfo.latestPrice,\n            tokenInfo.normalizationFactorForToken,\n            roundPrice\n        );\n        if (toReturn < minAmountToken) {\n            revert UnexpectedPriceDifference();\n        }\n        claims[msg.sender][round] += toReturn;\n        payable(fundsWallet).sendValue(msg.value);\n        emit PurchasedWithETH({\n            by: msg.sender,\n            code: code,\n            amountPurchasedETH: msg.value,\n            round: round,\n            roundPrice: roundPrice,\n            tokenPurchased: toReturn\n        });\n    }\n\n    /// @notice Purchases presale token with any token\n    /// @param token The purchase token\n    /// @param referenceNormalizationFactor The normalization factor\n    /// @param referenceTokenPrice The current price of token in 10 decimals\n    /// @param purchaseAmount The purchase amount\n    /// @param minAmountToken The minAmountToken user agrees to purchase\n    /// @param code The code is used to verify signature of the user\n    /// @param round The round in which user wants to purchase\n    /// @param deadline The deadline is validity of the signature\n    /// @param v The `v` signature parameter\n    /// @param r The `r` signature parameter\n    /// @param s The `s` signature parameter\n    function purchaseTokenWithToken(\n        IERC20 token,\n        uint8 referenceNormalizationFactor,\n        uint256 referenceTokenPrice,\n        uint256 purchaseAmount,\n        uint256 minAmountToken,\n        string memory code,\n        uint32 round,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external canBuy nonReentrant {\n        // The input must have been signed by the presale signer\n        _validatePurchaseWithToken(\n            token,\n            round,\n            deadline,\n            code,\n            referenceTokenPrice,\n            referenceNormalizationFactor,\n            v,\n            r,\n            s\n        );\n        _checkValue(purchaseAmount);\n\n        uint256 roundPrice = _getRoundPriceForToken(round, token);\n\n        (uint256 latestPrice, uint8 normalizationFactor) = _validatePrice(\n            token,\n            referenceTokenPrice,\n            referenceNormalizationFactor\n        );\n\n        uint256 toReturn = _calculateAndUpdateTokenAmount(purchaseAmount, latestPrice, normalizationFactor, roundPrice);\n        if (toReturn < minAmountToken) {\n            revert UnexpectedPriceDifference();\n        }\n        claims[msg.sender][round] += toReturn;\n\n        token.safeTransferFrom(msg.sender, fundsWallet, purchaseAmount);\n        emit PurchasedWithToken({\n            token: token,\n            tokenPrice: latestPrice,\n            by: msg.sender,\n            code: code,\n            amountPurchased: purchaseAmount,\n            tokenPurchased: toReturn,\n            round: round\n        });\n    }\n\n    /// @inheritdoc IPreSale\n    function purchaseWithClaim(\n        IERC20 token,\n        uint256 referenceTokenPrice,\n        uint8 referenceNormalizationFactor,\n        uint256 amount,\n        uint256 minAmountToken,\n        address recipient,\n        uint32 round\n    ) external payable canBuy nonReentrant {\n        if (msg.sender != claimsContract) {\n            revert OnlyClaims();\n        }\n        _checkBlacklist(recipient);\n        if (!allowedTokens[round][token].access) {\n            revert TokenDisallowed();\n        }\n        uint256 roundPrice = _getRoundPriceForToken(round, token);\n        (uint256 latestPrice, uint8 normalizationFactor) = _validatePrice(\n            token,\n            referenceTokenPrice,\n            referenceNormalizationFactor\n        );\n\n        uint256 toReturn = _calculateAndUpdateTokenAmount(amount, latestPrice, normalizationFactor, roundPrice);\n        if (toReturn < minAmountToken) {\n            revert UnexpectedPriceDifference();\n        }\n        claims[recipient][round] += toReturn;\n        if (token == ETH) {\n            payable(fundsWallet).sendValue(msg.value);\n        } else {\n            token.safeTransferFrom(claimsContract, fundsWallet, amount);\n        }\n        emit PurchasedWithClaimAmount({\n            by: recipient,\n            amount: amount,\n            token: token,\n            round: round,\n            tokenPrice: latestPrice,\n            tokenPurchased: toReturn\n        });\n    }\n\n    /// @dev Checks value, if zero then reverts\n    function _checkValue(uint256 value) private pure {\n        if (value == 0) {\n            revert ZeroValue();\n        }\n    }\n\n    /// @dev Validates blacklist address, round and deadline\n    function _validatePurchase(uint32 round, uint256 deadline, IERC20 token) private view {\n        if (block.timestamp > deadline) {\n            revert DeadlineExpired();\n        }\n        _checkBlacklist(msg.sender);\n        if (!allowedTokens[round][token].access) {\n            revert TokenDisallowed();\n        }\n        _verifyInRound(round);\n    }\n\n    /// @dev The helper function which verifies signature, signed by signerWallet, reverts if Invalid\n    function _verifyCode(string memory code, uint256 deadline, uint8 v, bytes32 r, bytes32 s) private view {\n        bytes32 encodedMessageHash = keccak256(abi.encodePacked(msg.sender, code, deadline));\n        _verifyMessage(encodedMessageHash, v, r, s);\n    }\n\n    /// @dev The helper function which verifies signature, signed by signerWallet, reverts if Invalid\n    function _verifyCodeWithPrice(\n        string memory code,\n        uint256 deadline,\n        uint256 referenceTokenPrice,\n        IERC20 token,\n        uint256 normalizationFactor,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) private view {\n        bytes32 encodedMessageHash = keccak256(\n            abi.encodePacked(msg.sender, code, referenceTokenPrice, deadline, token, normalizationFactor)\n        );\n        _verifyMessage(encodedMessageHash, v, r, s);\n    }\n\n    /// @dev Verifies the address that signed a hashed message (`hash`) with\n    /// `signature`\n    function _verifyMessage(bytes32 encodedMessageHash, uint8 v, bytes32 r, bytes32 s) private view {\n        if (signerWallet != ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(encodedMessageHash), v, r, s)) {\n            revert InvalidSignature();\n        }\n    }\n\n    /// @dev Checks that address is blacklisted or not\n    function _checkBlacklist(address which) private view {\n        if (blacklistAddress[which]) {\n            revert Blacklisted();\n        }\n    }\n\n    /// @dev Checks max cap and updates total purchases\n    function _updateTokenPurchases(uint256 newPurchase) private {\n        if (newPurchase + totalPurchases > maxCap) {\n            revert MaxCapReached();\n        }\n        totalPurchases += newPurchase;\n    }\n\n    /// @dev Validates round, deadline and signature\n    function _validatePurchaseWithETH(\n        uint256 amount,\n        uint32 round,\n        uint256 deadline,\n        string memory code,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) private view {\n        _checkValue(amount);\n        _validatePurchase(round, deadline, ETH);\n        _verifyCode(code, deadline, v, r, s);\n    }\n\n    /// @dev Validates round, deadline and signature\n    function _validatePurchaseWithToken(\n        IERC20 token,\n        uint32 round,\n        uint256 deadline,\n        string memory code,\n        uint256 referenceTokenPrice,\n        uint256 normalizationFactor,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) private view {\n        _validatePurchase(round, deadline, token);\n        _verifyCodeWithPrice(code, deadline, referenceTokenPrice, token, normalizationFactor, v, r, s);\n    }\n\n    /// @dev Validates round, deadline and signature\n    function _getRoundPriceForToken(uint32 round, IERC20 token) private view returns (uint256) {\n        uint256 customPrice = allowedTokens[round][token].customPrice;\n        uint256 roundPrice = customPrice > 0 ? customPrice : rounds[round].price;\n        return roundPrice;\n    }\n\n    /// @dev Calculates and update the token amount\n    function _calculateAndUpdateTokenAmount(\n        uint256 purchaseAmount,\n        uint256 referenceTokenPrice,\n        uint256 normalizationFactor,\n        uint256 roundPrice\n    ) private returns (uint256) {\n        // toReturn= (10**11 * 10**10 +10**15) -10**18 = 18 decimals\n        uint256 toReturn = (purchaseAmount * referenceTokenPrice * (10 ** normalizationFactor)) / roundPrice;\n        _updateTokenPurchases(toReturn);\n        return toReturn;\n    }\n\n    /// @dev Provides us live price of token from price feed or returns reference price and reverts if invalid\n    function _validatePrice(\n        IERC20 token,\n        uint256 referenceTokenPrice,\n        uint8 referenceNormalizationFactor\n    ) private view returns (uint256, uint8) {\n        TokenInfo memory tokenInfo = getLatestPrice(token);\n        if (tokenInfo.latestPrice != 0) {\n            if (referenceTokenPrice != 0 || referenceNormalizationFactor != 0) {\n                revert CodeSyncIssue();\n            }\n        }\n        //  If price feed isn't available,we fallback to the reference price\n        if (tokenInfo.latestPrice == 0) {\n            if (referenceTokenPrice == 0 || referenceNormalizationFactor == 0) {\n                revert ZeroValue();\n            }\n\n            tokenInfo.latestPrice = referenceTokenPrice;\n            tokenInfo.normalizationFactorForToken = referenceNormalizationFactor;\n        }\n        return (tokenInfo.latestPrice, tokenInfo.normalizationFactorForToken);\n    }\n}"
      },
      "contracts/Rounds.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport { TokenRegistry } from \"./TokenRegistry.sol\";\nimport { IRounds } from \"./IRounds.sol\";\n\nimport { ZeroAddress, ArrayLengthMismatch, ZeroLengthArray } from \"./Common.sol\";\n\n/// @title Rounds contract\n/// @notice Implements the round creation and updating of presale\n/// @dev The rounds contract allows you to create a round, update a round\n\nabstract contract Rounds is IRounds, Ownable, TokenRegistry {\n    /// @notice Thrown when round time is not started\n    error RoundNotStarted();\n\n    /// @notice Thrown when round time is ended\n    error RoundEnded();\n\n    /// @notice Thrown when Round is not created\n    error IncorrectRound();\n\n    /// @notice Thrown when new round price is less than previous round price\n    error PriceLessThanOldRound();\n\n    /// @notice Thrown when round start time is invalid\n    error InvalidStartTime();\n\n    /// @notice Thrown when round end time is invalid\n    error InvalidEndTime();\n\n    /// @notice Thrown when new price is invalid\n    error PriceInvalid();\n\n    /// @notice Thrown when startTime is incorrect when updating round\n    error IncorrectStartTime();\n\n    /// @notice Thrown when endTime is incorrect when updating round\n    error IncorrectEndTime();\n\n    /// @notice Thrown when round price is greater than next round while updating\n    error PriceGreaterThanNextRound();\n\n    /// @notice Thrown when Token is restricted in given round\n    error TokenDisallowed();\n\n    /// @notice The round index of last round created\n    uint32 internal immutable _startRound;\n\n    /// @notice The count of rounds created\n    uint32 internal _roundIndex;\n\n    /// @notice mapping gives us access info of the token in a given round\n    mapping(uint32 => mapping(IERC20 => AllowedToken)) public allowedTokens;\n\n    /// @notice mapping gives Round Data of each round\n    mapping(uint32 => RoundData) public rounds;\n\n    /// @member access The access of the token\n    /// @member customPrice The customPrice price in the round for the token\n    struct AllowedToken {\n        bool access;\n        uint256 customPrice;\n    }\n\n    /// @member startTime The start time of round\n    /// @member endTime The end time of round\n    /// @member price The price in usd per token\n    struct RoundData {\n        uint256 startTime;\n        uint256 endTime;\n        uint256 price;\n    }\n    /// @dev Emitted when creating a new round\n    event RoundCreated(uint32 indexed newRound, RoundData roundData);\n\n    /// @dev Emitted when round is updated\n    event RoundUpdated(uint32 indexed round, RoundData roundData);\n\n    /// @dev Emitted when token access is updated\n    event TokensAccessUpdated(uint32 indexed round, IERC20 indexed token, bool indexed access, uint256 customPrice);\n\n    /// @dev Constructor.\n    /// @param lastRound The last round created\n    constructor(uint32 lastRound) {\n        _startRound = lastRound;\n        _roundIndex = lastRound;\n    }\n\n    /// @notice Creates a new round\n    /// @param startTime The startTime of the round\n    /// @param endTime The endTime of the round\n    /// @param price The presale token price in 18 decimals, because our calculations returns a value in 36 decimals and to get returning value in 18 decimals we divide by round price\n    function createNewRound(uint256 startTime, uint256 endTime, uint256 price) external onlyOwner {\n        RoundData memory prevRoundData = rounds[_roundIndex];\n        uint32 newRound = ++_roundIndex;\n        if (price < prevRoundData.price) {\n            revert PriceLessThanOldRound();\n        }\n        if (startTime < prevRoundData.endTime) {\n            revert InvalidStartTime();\n        }\n        _verifyRound(startTime, endTime, price);\n        prevRoundData = RoundData({ startTime: startTime, endTime: endTime, price: price });\n        rounds[newRound] = prevRoundData;\n        emit RoundCreated({ newRound: newRound, roundData: prevRoundData });\n    }\n\n    /// @notice Updates the access of tokens in a given round\n    /// @param round The round in which you want to update\n    /// @param tokens addresses of the tokens\n    /// @param accesses The access for the tokens\n    /// @param customPrices The customPrice prices if any for the tokens\n    function updateAllowedTokens(\n        uint32 round,\n        IERC20[] calldata tokens,\n        bool[] calldata accesses,\n        uint256[] calldata customPrices\n    ) external onlyOwner {\n        uint256 tokensLength = tokens.length;\n        if (tokensLength == 0) {\n            revert ZeroLengthArray();\n        }\n        if (tokensLength != accesses.length || accesses.length != customPrices.length) {\n            revert ArrayLengthMismatch();\n        }\n        mapping(IERC20 => AllowedToken) storage selectedRound = allowedTokens[round];\n        for (uint256 i = 0; i < tokensLength; ++i) {\n            IERC20 token = tokens[i];\n\n            if (address(token) == address(0)) {\n                revert ZeroAddress();\n            }\n            AllowedToken memory allowedToken = AllowedToken({ access: accesses[i], customPrice: customPrices[i] });\n            selectedRound[token] = allowedToken;\n\n            emit TokensAccessUpdated({\n                round: round,\n                token: token,\n                access: allowedToken.access,\n                customPrice: allowedToken.customPrice\n            });\n        }\n    }\n\n    /// @notice Updates round data\n    /// @param round The Round that will be updated\n    /// @param startTime The StartTime of the round\n    /// @param endTime The EndTime of the round\n    /// @param price The price of the round in 18 decimals\n    function updateRound(uint32 round, uint256 startTime, uint256 endTime, uint256 price) external onlyOwner {\n        if (round <= _startRound || round > _roundIndex) {\n            revert IncorrectRound();\n        }\n        RoundData memory previousRound = rounds[round - 1];\n        RoundData memory nextRound = rounds[round + 1];\n        if (startTime < previousRound.endTime) {\n            revert IncorrectStartTime();\n        }\n        if (round != _roundIndex && endTime > nextRound.startTime) {\n            revert IncorrectEndTime();\n        }\n        if (price < previousRound.price) {\n            revert PriceLessThanOldRound();\n        }\n        if (round != _roundIndex && price > nextRound.price) {\n            revert PriceGreaterThanNextRound();\n        }\n        _verifyRound(startTime, endTime, price);\n        rounds[round] = RoundData({ startTime: startTime, endTime: endTime, price: price });\n        emit RoundUpdated({ round: round, roundData: rounds[round] });\n    }\n\n    /// @notice Returns total rounds created\n    /// @return The Round count\n    function getRoundCount() external view returns (uint32) {\n        return _roundIndex;\n    }\n\n    /// @dev Validates array length and values\n    function _validateArrays(uint256 firstLength, uint256 secondLength) internal pure {\n        if (firstLength == 0) {\n            revert ZeroLengthArray();\n        }\n        if (firstLength != secondLength) {\n            revert ArrayLengthMismatch();\n        }\n    }\n\n    /// @dev Checks round start and end time, reverts if Invalid\n    function _verifyInRound(uint32 round) internal view {\n        RoundData memory dataRound = rounds[round];\n        if (block.timestamp < dataRound.startTime) {\n            revert RoundNotStarted();\n        }\n        if (block.timestamp >= dataRound.endTime) {\n            revert RoundEnded();\n        }\n    }\n\n    /// @dev Checks the validity of startTime, endTime and price\n    function _verifyRound(uint256 startTime, uint256 endTime, uint256 price) internal view {\n        if (startTime < block.timestamp) {\n            revert InvalidStartTime();\n        }\n        if (endTime <= startTime) {\n            revert InvalidEndTime();\n        }\n        if (price == 0) {\n            revert PriceInvalid();\n        }\n    }\n}"
      },
      "contracts/TokenRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AggregatorV3Interface } from \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\nimport { ZeroAddress, ArrayLengthMismatch, ZeroLengthArray, IdenticalValue } from \"./Common.sol\";\n\n/// @title Tokens Registry contract\n/// @notice Implements the price feed of the tokens\n\nabstract contract TokenRegistry is Ownable {\n    /// @notice Gives us onchain price oracle address of the token\n    mapping(IERC20 => PriceFeedData) public tokenData;\n\n    /// @dev Emitted when address of Chainlink price feed contract is added for the token\n    event TokenDataAdded(IERC20 token, PriceFeedData data);\n\n    /// @member priceFeed The Chainlink price feed address\n    /// @member normalizationFactorForToken The normalization factor to achieve return value of 18 decimals, while calculating presale token purchases and always with different token decimals\n    /// @member tolerance The pricefeed live price should be updated in tolerance time to get better price\n    struct PriceFeedData {\n        AggregatorV3Interface priceFeed;\n        uint8 normalizationFactorForToken;\n        uint256 tolerance;\n    }\n\n    /// @notice Sets token price feeds and normalization factors\n    /// @param tokens The addresses of the tokens\n    /// @param priceFeedData Contains the price feed of the tokens, tolerance and the normalization factor\n    function setTokenPriceFeed(IERC20[] calldata tokens, PriceFeedData[] calldata priceFeedData) external onlyOwner {\n        uint256 tokensLength = tokens.length;\n        if (tokensLength == 0) {\n            revert ZeroLengthArray();\n        }\n        if (tokensLength != priceFeedData.length) {\n            revert ArrayLengthMismatch();\n        }\n        for (uint256 i = 0; i < tokensLength; ++i) {\n            PriceFeedData calldata data = priceFeedData[i];\n            IERC20 token = tokens[i];\n            PriceFeedData memory currentPriceFeedData = tokenData[token];\n            if (address(token) == address(0) || address(data.priceFeed) == address(0)) {\n                revert ZeroAddress();\n            }\n            if (\n                currentPriceFeedData.priceFeed == data.priceFeed &&\n                currentPriceFeedData.normalizationFactorForToken == data.normalizationFactorForToken &&\n                currentPriceFeedData.tolerance == data.tolerance\n            ) {\n                revert IdenticalValue();\n            }\n            emit TokenDataAdded({ token: token, data: data });\n            tokenData[token] = data;\n        }\n    }\n}"
      }
    },
    "settings": {
      "viaIR": true,
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}