creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@1inch/solidity-utils/contracts/interfaces/IDaiLikePermit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IDaiLikePermit {\n    function permit(\n        address holder,\n        address spender,\n        uint256 nonce,\n        uint256 expiry,\n        bool allowed,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n}\n"
      },
      "@1inch/solidity-utils/contracts/interfaces/IPermit2.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IPermit2 {\n    struct PermitDetails {\n        // ERC20 token address\n        address token;\n        // the maximum amount allowed to spend\n        uint160 amount;\n        // timestamp at which a spender's token allowances become invalid\n        uint48 expiration;\n        // an incrementing value indexed per owner,token,and spender for each signature\n        uint48 nonce;\n    }\n    /// @notice The permit message signed for a single token allownce\n    struct PermitSingle {\n        // the permit data for a single token alownce\n        PermitDetails details;\n        // address permissioned on the allowed tokens\n        address spender;\n        // deadline on the permit signature\n        uint256 sigDeadline;\n    }\n    /// @notice Packed allowance\n    struct PackedAllowance {\n        // amount allowed\n        uint160 amount;\n        // permission expiry\n        uint48 expiration;\n        // an incrementing value indexed per owner,token,and spender for each signature\n        uint48 nonce;\n    }\n\n    function transferFrom(address user, address spender, uint160 amount, address token) external;\n\n    function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;\n\n    function allowance(address user, address token, address spender) external view returns (PackedAllowance memory);\n}\n"
      },
      "@1inch/solidity-utils/contracts/interfaces/IWETH.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    event Deposit(address indexed dst, uint256 wad);\n\n    event Withdrawal(address indexed src, uint256 wad);\n\n    function deposit() external payable;\n\n    function withdraw(uint256 amount) external;\n}\n"
      },
      "@1inch/solidity-utils/contracts/libraries/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\n\nlibrary ECDSA {\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    uint256 private constant _S_BOUNDARY = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 + 1;\n    uint256 private constant _COMPACT_S_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n    uint256 private constant _COMPACT_V_SHIFT = 255;\n\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal view returns (address signer) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            if lt(s, _S_BOUNDARY) {\n                let ptr := mload(0x40)\n\n                mstore(ptr, hash)\n                mstore(add(ptr, 0x20), v)\n                mstore(add(ptr, 0x40), r)\n                mstore(add(ptr, 0x60), s)\n                mstore(0, 0)\n                pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))\n                signer := mload(0)\n            }\n        }\n    }\n\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal view returns (address signer) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let s := and(vs, _COMPACT_S_MASK)\n            if lt(s, _S_BOUNDARY) {\n                let ptr := mload(0x40)\n\n                mstore(ptr, hash)\n                mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))\n                mstore(add(ptr, 0x40), r)\n                mstore(add(ptr, 0x60), s)\n                mstore(0, 0)\n                pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))\n                signer := mload(0)\n            }\n        }\n    }\n\n    /// @dev WARNING!!!\n    /// There is a known signature malleability issue with two representations of signatures!\n    /// Even though this function is able to verify both standard 65-byte and compact 64-byte EIP-2098 signatures\n    /// one should never use raw signatures for any kind of invalidation logic in their code.\n    /// As the standard and compact representations are interchangeable any invalidation logic that relies on\n    /// signature uniqueness will get rekt.\n    /// More info: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h\n    function recover(bytes32 hash, bytes calldata signature) internal view returns (address signer) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            // memory[ptr:ptr+0x80] = (hash, v, r, s)\n            switch signature.length\n            case 65 {\n                // memory[ptr+0x20:ptr+0x80] = (v, r, s)\n                mstore(add(ptr, 0x20), byte(0, calldataload(add(signature.offset, 0x40))))\n                calldatacopy(add(ptr, 0x40), signature.offset, 0x40)\n            }\n            case 64 {\n                // memory[ptr+0x20:ptr+0x80] = (v, r, s)\n                let vs := calldataload(add(signature.offset, 0x20))\n                mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))\n                calldatacopy(add(ptr, 0x40), signature.offset, 0x20)\n                mstore(add(ptr, 0x60), and(vs, _COMPACT_S_MASK))\n            }\n            default {\n                ptr := 0\n            }\n\n            if ptr {\n                if lt(mload(add(ptr, 0x60)), _S_BOUNDARY) {\n                    // memory[ptr:ptr+0x20] = (hash)\n                    mstore(ptr, hash)\n\n                    mstore(0, 0)\n                    pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))\n                    signer := mload(0)\n                }\n            }\n        }\n    }\n\n    function recoverOrIsValidSignature(\n        address signer,\n        bytes32 hash,\n        bytes calldata signature\n    ) internal view returns (bool success) {\n        if (signer == address(0)) return false;\n        if ((signature.length == 64 || signature.length == 65) && recover(hash, signature) == signer) {\n            return true;\n        }\n        return isValidSignature(signer, hash, signature);\n    }\n\n    function recoverOrIsValidSignature(\n        address signer,\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal view returns (bool success) {\n        if (signer == address(0)) return false;\n        if (recover(hash, v, r, s) == signer) {\n            return true;\n        }\n        return isValidSignature(signer, hash, v, r, s);\n    }\n\n    function recoverOrIsValidSignature(\n        address signer,\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal view returns (bool success) {\n        if (signer == address(0)) return false;\n        if (recover(hash, r, vs) == signer) {\n            return true;\n        }\n        return isValidSignature(signer, hash, r, vs);\n    }\n\n    function recoverOrIsValidSignature65(\n        address signer,\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal view returns (bool success) {\n        if (signer == address(0)) return false;\n        if (recover(hash, r, vs) == signer) {\n            return true;\n        }\n        return isValidSignature65(signer, hash, r, vs);\n    }\n\n    function isValidSignature(\n        address signer,\n        bytes32 hash,\n        bytes calldata signature\n    ) internal view returns (bool success) {\n        // (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature));\n        // return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;\n        bytes4 selector = IERC1271.isValidSignature.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            mstore(ptr, selector)\n            mstore(add(ptr, 0x04), hash)\n            mstore(add(ptr, 0x24), 0x40)\n            mstore(add(ptr, 0x44), signature.length)\n            calldatacopy(add(ptr, 0x64), signature.offset, signature.length)\n            if staticcall(gas(), signer, ptr, add(0x64, signature.length), 0, 0x20) {\n                success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))\n            }\n        }\n    }\n\n    function isValidSignature(\n        address signer,\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal view returns (bool success) {\n        bytes4 selector = IERC1271.isValidSignature.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            mstore(ptr, selector)\n            mstore(add(ptr, 0x04), hash)\n            mstore(add(ptr, 0x24), 0x40)\n            mstore(add(ptr, 0x44), 65)\n            mstore(add(ptr, 0x64), r)\n            mstore(add(ptr, 0x84), s)\n            mstore8(add(ptr, 0xa4), v)\n            if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {\n                success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))\n            }\n        }\n    }\n\n    function isValidSignature(\n        address signer,\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal view returns (bool success) {\n        // (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs)));\n        // return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;\n        bytes4 selector = IERC1271.isValidSignature.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            mstore(ptr, selector)\n            mstore(add(ptr, 0x04), hash)\n            mstore(add(ptr, 0x24), 0x40)\n            mstore(add(ptr, 0x44), 64)\n            mstore(add(ptr, 0x64), r)\n            mstore(add(ptr, 0x84), vs)\n            if staticcall(gas(), signer, ptr, 0xa4, 0, 0x20) {\n                success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))\n            }\n        }\n    }\n\n    function isValidSignature65(\n        address signer,\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal view returns (bool success) {\n        // (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs & ~uint256(1 << 255), uint8(vs >> 255))));\n        // return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;\n        bytes4 selector = IERC1271.isValidSignature.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            mstore(ptr, selector)\n            mstore(add(ptr, 0x04), hash)\n            mstore(add(ptr, 0x24), 0x40)\n            mstore(add(ptr, 0x44), 65)\n            mstore(add(ptr, 0x64), r)\n            mstore(add(ptr, 0x84), and(vs, _COMPACT_S_MASK))\n            mstore8(add(ptr, 0xa4), add(27, shr(_COMPACT_V_SHIFT, vs)))\n            if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {\n                success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))\n            }\n        }\n    }\n\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 res) {\n        // 32 is the length in bytes of hash, enforced by the type signature above\n        // return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            mstore(0, 0x19457468657265756d205369676e6564204d6573736167653a0a333200000000) // \"\\x19Ethereum Signed Message:\\n32\"\n            mstore(28, hash)\n            res := keccak256(0, 60)\n        }\n    }\n\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 res) {\n        // return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n            mstore(ptr, 0x1901000000000000000000000000000000000000000000000000000000000000) // \"\\x19\\x01\"\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            res := keccak256(ptr, 66)\n        }\n    }\n}\n"
      },
      "@1inch/solidity-utils/contracts/libraries/RevertReasonForwarder.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/// @title Revert reason forwarder.\nlibrary RevertReasonForwarder {\n    /// @dev Forwards latest externall call revert.\n    function reRevert() internal pure {\n        // bubble up revert reason from latest external call\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n            returndatacopy(ptr, 0, returndatasize())\n            revert(ptr, returndatasize())\n        }\n    }\n\n    /// @dev Returns latest external call revert reason.\n    function reReason() internal pure returns (bytes memory reason) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            reason := mload(0x40)\n            let length := returndatasize()\n            mstore(reason, length)\n            returndatacopy(add(reason, 0x20), 0, length)\n            mstore(0x40, add(reason, add(0x20, length)))\n        }\n    }\n}\n"
      },
      "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport \"../interfaces/IDaiLikePermit.sol\";\nimport \"../interfaces/IPermit2.sol\";\nimport \"../interfaces/IWETH.sol\";\nimport \"../libraries/RevertReasonForwarder.sol\";\n\n/**\n * @title Implements efficient safe methods for ERC20 interface.\n * @notice Compared to the standard ERC20, this implementation offers several enhancements:\n * 1. more gas-efficient, providing significant savings in transaction costs.\n * 2. support for different permit implementations\n * 3. forceApprove functionality\n * 4. support for WETH deposit and withdraw\n */\nlibrary SafeERC20 {\n    error SafeTransferFailed();\n    error SafeTransferFromFailed();\n    error ForceApproveFailed();\n    error SafeIncreaseAllowanceFailed();\n    error SafeDecreaseAllowanceFailed();\n    error SafePermitBadLength();\n    error Permit2TransferAmountTooHigh();\n\n    // Uniswap Permit2 address\n    address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\n    bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857;  // SafePermitBadLength.selector\n    uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;\n\n    /**\n     * @notice Fetches the balance of a specific ERC20 token held by an account.\n     * Consumes less gas then regular `ERC20.balanceOf`.\n     * @dev Note that the implementation does not perform dirty bits cleaning, so it is the\n     * responsibility of the caller to make sure that the higher 96 bits of the `account` parameter are clean.\n     * @param token The IERC20 token contract for which the balance will be fetched.\n     * @param account The address of the account whose token balance will be fetched.\n     * @return tokenBalance The balance of the specified ERC20 token held by the account.\n     */\n    function safeBalanceOf(\n        IERC20 token,\n        address account\n    ) internal view returns(uint256 tokenBalance) {\n        bytes4 selector = IERC20.balanceOf.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            mstore(0x00, selector)\n            mstore(0x04, account)\n            let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20)\n            tokenBalance := mload(0)\n\n            if or(iszero(success), lt(returndatasize(), 0x20)) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @notice Attempts to safely transfer tokens from one address to another.\n     * @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.\n     * Either requires `true` in return data, or requires target to be smart-contract and empty return data.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.\n     * @param token The IERC20 token contract from which the tokens will be transferred.\n     * @param from The address from which the tokens will be transferred.\n     * @param to The address to which the tokens will be transferred.\n     * @param amount The amount of tokens to transfer.\n     * @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom.\n     */\n    function safeTransferFromUniversal(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount,\n        bool permit2\n    ) internal {\n        if (permit2) {\n            safeTransferFromPermit2(token, from, to, amount);\n        } else {\n            safeTransferFrom(token, from, to, amount);\n        }\n    }\n\n    /**\n     * @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard.\n     * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.\n     * @param token The IERC20 token contract from which the tokens will be transferred.\n     * @param from The address from which the tokens will be transferred.\n     * @param to The address to which the tokens will be transferred.\n     * @param amount The amount of tokens to transfer.\n     */\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        bytes4 selector = token.transferFrom.selector;\n        bool success;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), from)\n            mstore(add(data, 0x24), to)\n            mstore(add(data, 0x44), amount)\n            success := call(gas(), token, 0, data, 100, 0x0, 0x20)\n            if success {\n                switch returndatasize()\n                case 0 {\n                    success := gt(extcodesize(token), 0)\n                }\n                default {\n                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))\n                }\n            }\n        }\n        if (!success) revert SafeTransferFromFailed();\n    }\n\n    /**\n     * @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard.\n     * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.\n     * @param token The IERC20 token contract from which the tokens will be transferred.\n     * @param from The address from which the tokens will be transferred.\n     * @param to The address to which the tokens will be transferred.\n     * @param amount The amount of tokens to transfer.\n     */\n    function safeTransferFromPermit2(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount\n    ) internal {\n        if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();\n        bytes4 selector = IPermit2.transferFrom.selector;\n        bool success;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), from)\n            mstore(add(data, 0x24), to)\n            mstore(add(data, 0x44), amount)\n            mstore(add(data, 0x64), token)\n            success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)\n            if success {\n                success := gt(extcodesize(_PERMIT2), 0)\n            }\n        }\n        if (!success) revert SafeTransferFromFailed();\n    }\n\n    /**\n     * @notice Attempts to safely transfer tokens to another address.\n     * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `to` parameter are clean.\n     * @param token The IERC20 token contract from which the tokens will be transferred.\n     * @param to The address to which the tokens will be transferred.\n     * @param value The amount of tokens to transfer.\n     */\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        if (!_makeCall(token, token.transfer.selector, to, value)) {\n            revert SafeTransferFailed();\n        }\n    }\n\n    /**\n     * @notice Attempts to approve a spender to spend a certain amount of tokens.\n     * @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.\n     * @param token The IERC20 token contract on which the call will be made.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     */\n    function forceApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        if (!_makeCall(token, token.approve.selector, spender, value)) {\n            if (\n                !_makeCall(token, token.approve.selector, spender, 0) ||\n                !_makeCall(token, token.approve.selector, spender, value)\n            ) {\n                revert ForceApproveFailed();\n            }\n        }\n    }\n\n    /**\n     * @notice Safely increases the allowance of a spender.\n     * @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction.\n     * Then uses `forceApprove` to increase the allowance.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.\n     * @param token The IERC20 token contract on which the call will be made.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to increase the allowance by.\n     */\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 allowance = token.allowance(address(this), spender);\n        if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();\n        forceApprove(token, spender, allowance + value);\n    }\n\n    /**\n     * @notice Safely decreases the allowance of a spender.\n     * @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction.\n     * Then uses `forceApprove` to increase the allowance.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `spender` parameter are clean.\n     * @param token The IERC20 token contract on which the call will be made.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to decrease the allowance by.\n     */\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 allowance = token.allowance(address(this), spender);\n        if (value > allowance) revert SafeDecreaseAllowanceFailed();\n        forceApprove(token, spender, allowance - value);\n    }\n\n    /**\n     * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.\n     * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).\n     * @dev Wraps `tryPermit` function and forwards revert reason if permit fails.\n     * @param token The IERC20 token to execute the permit function on.\n     * @param permit The permit data to be used in the function call.\n     */\n    function safePermit(IERC20 token, bytes calldata permit) internal {\n        if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();\n    }\n\n    /**\n     * @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.\n     * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).\n     * @dev Wraps `tryPermit` function and forwards revert reason if permit fails.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean.\n     * @param token The IERC20 token to execute the permit function on.\n     * @param owner The owner of the tokens for which the permit is made.\n     * @param spender The spender allowed to spend the tokens by the permit.\n     * @param permit The permit data to be used in the function call.\n     */\n    function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {\n        if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();\n    }\n\n    /**\n     * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.\n     * @dev Invokes `tryPermit` with sender as owner and contract as spender.\n     * @param token The IERC20 token to execute the permit function on.\n     * @param permit The permit data to be used in the function call.\n     * @return success Returns true if the permit function was successfully executed, false otherwise.\n     */\n    function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {\n        return tryPermit(token, msg.sender, address(this), permit);\n    }\n\n    /**\n     * @notice The function attempts to call the permit function on a given ERC20 token.\n     * @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2.\n     * It accommodates both Compact and Full formats of these permit types.\n     * Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter\n     * for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by\n     * gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and\n     * zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one\n     * before invocation for optimized performance.\n     * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of\n     * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean.\n     * @param token The address of the ERC20 token on which to call the permit function.\n     * @param owner The owner of the tokens. This address should have signed the off-chain permit.\n     * @param spender The address which will be approved for transfer of tokens.\n     * @param permit The off-chain permit data, containing different fields depending on the type of permit function.\n     * @return success A boolean indicating whether the permit call was successful.\n     */\n    function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {\n        // load function selectors for different permit standards\n        bytes4 permitSelector = IERC20Permit.permit.selector;\n        bytes4 daiPermitSelector = IDaiLikePermit.permit.selector;\n        bytes4 permit2Selector = IPermit2.permit.selector;\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let ptr := mload(0x40)\n\n            // Switch case for different permit lengths, indicating different permit standards\n            switch permit.length\n            // Compact IERC20Permit\n            case 100 {\n                mstore(ptr, permitSelector)     // store selector\n                mstore(add(ptr, 0x04), owner)   // store owner\n                mstore(add(ptr, 0x24), spender) // store spender\n\n                // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)\n                {  // stack too deep\n                    let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23\n                    let vs := calldataload(add(permit.offset, 0x44))                 // loads permit.offset 0x44..0x63\n\n                    calldatacopy(add(ptr, 0x44), permit.offset, 0x20)            // store value     = copy permit.offset 0x00..0x19\n                    mstore(add(ptr, 0x64), sub(deadline, 1))                     // store deadline  = deadline - 1\n                    mstore(add(ptr, 0x84), add(27, shr(255, vs)))                // store v         = most significant bit of vs + 27 (27 or 28)\n                    calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r         = copy permit.offset 0x24..0x43\n                    mstore(add(ptr, 0xc4), shr(1, shl(1, vs)))                   // store s         = vs without most significant bit\n                }\n                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)\n            }\n            // Compact IDaiLikePermit\n            case 72 {\n                mstore(ptr, daiPermitSelector)  // store selector\n                mstore(add(ptr, 0x04), owner)   // store owner\n                mstore(add(ptr, 0x24), spender) // store spender\n\n                // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)\n                {  // stack too deep\n                    let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07\n                    let vs := calldataload(add(permit.offset, 0x28))               // loads permit.offset 0x28..0x47\n\n                    mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce   = copy permit.offset 0x00..0x03\n                    mstore(add(ptr, 0x64), sub(expiry, 1))                        // store expiry  = expiry - 1\n                    mstore(add(ptr, 0x84), true)                                  // store allowed = true\n                    mstore(add(ptr, 0xa4), add(27, shr(255, vs)))                 // store v       = most significant bit of vs + 27 (27 or 28)\n                    calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20)  // store r       = copy permit.offset 0x08..0x27\n                    mstore(add(ptr, 0xe4), shr(1, shl(1, vs)))                    // store s       = vs without most significant bit\n                }\n                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0x104, 0, 0)\n            }\n            // IERC20Permit\n            case 224 {\n                mstore(ptr, permitSelector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata\n                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)\n            }\n            // IDaiLikePermit\n            case 256 {\n                mstore(ptr, daiPermitSelector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata\n                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)\n                success := call(gas(), token, 0, ptr, 0x104, 0, 0)\n            }\n            // Compact IPermit2\n            case 96 {\n                // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)\n                mstore(ptr, permit2Selector)  // store selector\n                mstore(add(ptr, 0x04), owner) // store owner\n                mstore(add(ptr, 0x24), token) // store token\n\n                calldatacopy(add(ptr, 0x50), permit.offset, 0x14)             // store amount = copy permit.offset 0x00..0x13\n                // and(0xffffffffffff, ...) - conversion to uint48\n                mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)\n                mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b\n                mstore(add(ptr, 0xa4), spender)                               // store spender\n                // and(0xffffffffffff, ...) - conversion to uint48\n                mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff)\n                mstore(add(ptr, 0xe4), 0x100)                                 // store offset = 256\n                mstore(add(ptr, 0x104), 0x40)                                 // store length = 64\n                calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r      = copy permit.offset 0x20..0x3f\n                calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs     = copy permit.offset 0x40..0x5f\n                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)\n                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)\n            }\n            // IPermit2\n            case 352 {\n                mstore(ptr, permit2Selector)\n                calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata\n                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)\n                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)\n            }\n            // Unknown\n            default {\n                mstore(ptr, _PERMIT_LENGTH_ERROR)\n                revert(ptr, 4)\n            }\n        }\n    }\n\n    /**\n     * @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns.\n     * @param token The IERC20 token contract on which the call will be made.\n     * @param selector The function signature that is to be called on the token contract.\n     * @param to The address to which the token amount will be transferred.\n     * @param amount The token amount to be transferred.\n     * @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.\n     * In case of success but no returned data, validates that the contract code exists.\n     * In case of returned data, ensures that it's a boolean `true`.\n     */\n    function _makeCall(\n        IERC20 token,\n        bytes4 selector,\n        address to,\n        uint256 amount\n    ) private returns (bool success) {\n        assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n            let data := mload(0x40)\n\n            mstore(data, selector)\n            mstore(add(data, 0x04), to)\n            mstore(add(data, 0x24), amount)\n            success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)\n            if success {\n                switch returndatasize()\n                case 0 {\n                    success := gt(extcodesize(token), 0)\n                }\n                default {\n                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))\n                }\n            }\n        }\n    }\n\n    /**\n     * @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`.\n     * @param weth The IWETH token contract.\n     * @param amount The amount of Ether to deposit into the IWETH contract.\n     */\n    function safeDeposit(IWETH weth, uint256 amount) internal {\n        if (amount > 0) {\n            bytes4 selector = IWETH.deposit.selector;\n            assembly (\"memory-safe\") { // solhint-disable-line no-inline-assembly\n                mstore(0, selector)\n                if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) {\n                    let ptr := mload(0x40)\n                    returndatacopy(ptr, 0, returndatasize())\n                    revert(ptr, returndatasize())\n                }\n            }\n        }\n    }\n\n    /**\n     * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`.\n     * @dev Uses inline assembly to interact with the IWETH contract.\n     * @param weth The IWETH token contract.\n     * @param amount The amount of wrapped Ether to withdraw from the IWETH contract.\n     */\n    function safeWithdraw(IWETH weth, uint256 amount) internal {\n        bytes4 selector = IWETH.withdraw.selector;\n        assembly (\"memory-safe\") {  // solhint-disable-line no-inline-assembly\n            mstore(0, selector)\n            mstore(4, amount)\n            if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient.\n     * Consumes less gas then regular `IWETH.withdraw`.\n     * @param weth The IWETH token contract.\n     * @param amount The amount of wrapped Ether to withdraw from the IWETH contract.\n     * @param to The recipient of the withdrawn Ether.\n     */\n    function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal {\n        safeWithdraw(weth, amount);\n        if (to != address(this)) {\n            assembly (\"memory-safe\") {  // solhint-disable-line no-inline-assembly\n                if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) {\n                    let ptr := mload(0x40)\n                    returndatacopy(ptr, 0, returndatasize())\n                    revert(ptr, returndatasize())\n                }\n            }\n        }\n    }\n}\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/interfaces/IERC1271.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n */\ninterface IERC1271 {\n    /**\n     * @dev Should return whether the signature provided is valid for the provided data\n     * @param hash      Hash of the data to be signed\n     * @param signature Signature byte array associated with _data\n     */\n    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\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/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/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"
      },
      "contracts/interfaces/ISignatureMerkleDrop128.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\npragma abicoder v1;\n\n// Allows anyone to claim a token if they exist in a merkle root.\ninterface ISignatureMerkleDrop128 {\n    error InvalidProof();\n    error DropAlreadyClaimed();\n\n    // Returns the address of the token distributed by this contract.\n    function token() external view returns (address);\n    // Returns the merkle root of the merkle tree containing account balances available to claim.\n    function merkleRoot() external view returns (bytes16);\n    // Returns the tree depth of the merkle tree containing account balances available to claim.\n    function depth() external view returns (uint256);\n    // Claim the given amount of the token to the given address. Reverts if the inputs are invalid.\n    function claim(address receiver, uint256 amount, bytes calldata merkleProof, bytes calldata signature) external;\n    // Verifies that given leaf and merkle proof matches given merkle root and returns leaf index.\n    function verify(bytes calldata proof, bytes16 root, bytes16 leaf) external view returns (bool valid, uint256 index);\n    // Returns true if the index has been marked claimed.\n    function isClaimed(uint256 index) external view returns (bool);\n}\n"
      },
      "contracts/SignatureMerkleDrop128.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.23;\n\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Ownable } from  \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { SafeERC20, IERC20 } from  \"@1inch/solidity-utils/contracts/libraries/SafeERC20.sol\";\nimport { ECDSA } from  \"@1inch/solidity-utils/contracts/libraries/ECDSA.sol\";\n\nimport { ISignatureMerkleDrop128 } from  \"./interfaces/ISignatureMerkleDrop128.sol\";\n\ncontract SignatureMerkleDrop128 is ISignatureMerkleDrop128, Ownable {\n    using Address for address payable;\n    using SafeERC20 for IERC20;\n\n    /* solhint-disable immutable-vars-naming */\n    address public immutable override token;\n    bytes16 public immutable override merkleRoot;\n    uint256 public immutable override depth;\n    /* solhint-enable immutable-vars-naming */\n\n    // This is a packed array of booleans.\n    mapping(uint256 => uint256) private _claimedBitMap;\n\n    uint256 private constant _CLAIM_GAS_COST = 60000;\n\n    receive() external payable {}  // solhint-disable-line no-empty-blocks\n\n    constructor(address token_, bytes16 merkleRoot_, uint256 depth_) Ownable(msg.sender) {\n        token = token_;\n        merkleRoot = merkleRoot_;\n        depth = depth_;\n    }\n\n    function claim(address receiver, uint256 amount, bytes calldata merkleProof, bytes calldata signature) external override {\n        bytes32 signedHash = ECDSA.toEthSignedMessageHash(keccak256(abi.encodePacked(receiver)));\n        address account = ECDSA.recover(signedHash, signature);\n        // Verify the merkle proof.\n        bytes16 node = bytes16(keccak256(abi.encodePacked(account, amount)));\n        (bool valid, uint256 index) = _verifyAsm(merkleProof, merkleRoot, node);\n        if (!valid) revert InvalidProof();\n        _invalidate(index);\n        IERC20(token).safeTransfer(receiver, amount);\n        _cashback();\n    }\n\n    function verify(bytes calldata proof, bytes16 root, bytes16 leaf) external view returns (bool valid, uint256 index) {\n        return _verifyAsm(proof, root, leaf);\n    }\n\n    function verify(bytes calldata proof, bytes16 leaf) external view returns (bool valid, uint256 index) {\n        return _verifyAsm(proof, merkleRoot, leaf);\n    }\n\n    function isClaimed(uint256 index) external view override returns (bool) {\n        uint256 claimedWordIndex = index / 256;\n        uint256 claimedBitIndex = index % 256;\n        uint256 claimedWord = _claimedBitMap[claimedWordIndex];\n        uint256 mask = (1 << claimedBitIndex);\n        return claimedWord & mask == mask;\n    }\n\n    function _cashback() private {\n        uint256 balance = address(this).balance;\n        if (balance > 0) {\n            // solhint-disable-next-line avoid-tx-origin\n            payable(tx.origin).sendValue(Math.min(block.basefee * _CLAIM_GAS_COST, balance));\n        }\n    }\n\n    function _invalidate(uint256 index) private {\n        uint256 claimedWordIndex = index >> 8;\n        uint256 claimedBitIndex = index & 0xff;\n        uint256 claimedWord = _claimedBitMap[claimedWordIndex];\n        uint256 newClaimedWord = claimedWord | (1 << claimedBitIndex);\n        if (claimedWord == newClaimedWord) revert DropAlreadyClaimed();\n        _claimedBitMap[claimedWordIndex] = newClaimedWord;\n    }\n\n    function _verifyAsm(bytes calldata proof, bytes16 root, bytes16 leaf) private view returns (bool valid, uint256 index) {\n        /// @solidity memory-safe-assembly\n        assembly {  // solhint-disable-line no-inline-assembly\n            let ptr := proof.offset\n            let mask := 1\n\n            for { let end := add(ptr, proof.length) } lt(ptr, end) { ptr := add(ptr, 0x10) } {\n                let node := calldataload(ptr)\n\n                switch lt(leaf, node)\n                case 1 {\n                    mstore(0x00, leaf)\n                    mstore(0x10, node)\n                }\n                default {\n                    mstore(0x00, node)\n                    mstore(0x10, leaf)\n                    index := or(mask, index)\n                }\n\n                leaf := keccak256(0x00, 0x20)\n                mask := shl(1, mask)\n            }\n\n            valid := iszero(shr(128, xor(root, leaf)))\n        }\n        unchecked {\n            index <<= depth - proof.length / 16;\n        }\n    }\n\n    function rescueFunds(address token_, uint256 amount) external onlyOwner {\n        if (token_ == address(0)) {\n            payable(msg.sender).sendValue(amount);\n        } else {\n            IERC20(token_).safeTransfer(msg.sender, amount);\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "evmVersion": "shanghai",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}