{
  "address": "0x08769D484a7Cd9c4A98E928D9E270221F3E8578c",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "addr",
          "type": "bytes"
        }
      ],
      "name": "InvalidAddressFormat",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "NotImplemented",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        },
        {
          "internalType": "bytes",
          "name": "context",
          "type": "bytes"
        }
      ],
      "name": "resolve",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "pure",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0x073a2781e7de2952710c167993a7900eb4c2c3838aeea1640666744aa7452dc8",
  "receipt": {
    "to": null,
    "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859",
    "contractAddress": "0x08769D484a7Cd9c4A98E928D9E270221F3E8578c",
    "transactionIndex": 98,
    "gasUsed": "1116071",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xa2aa6d335649626902472977466df67c0a08f739bc0fe0bef2ff7d5d900c4bfc",
    "transactionHash": "0x073a2781e7de2952710c167993a7900eb4c2c3838aeea1640666744aa7452dc8",
    "logs": [],
    "blockNumber": 20426738,
    "cumulativeGasUsed": "11217248",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "numDeployments": 2,
  "solcInputHash": "96d118177ae253bdd3815d2757c11cd9",
  "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"addr\",\"type\":\"bytes\"}],\"name\":\"InvalidAddressFormat\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Resolves names on ENS by interpreting record data stored in a DNS TXT record.      This resolver implements the IExtendedDNSResolver interface, meaning that when      a DNS name specifies it as the resolver via a TXT record, this resolver's      resolve() method is invoked, and is passed any additional information from that      text record. This resolver implements a simple text parser allowing a variety      of records to be specified in text, which will then be used to resolve the name      in ENS.      To use this, set a TXT record on your DNS name in the following format:          ENS1 <address or name of ExtendedDNSResolver> <record data>      For example:          ENS1 2.dnsname.ens.eth a[60]=0x1234...      The record data consists of a series of key=value pairs, separated by spaces. Keys      may have an optional argument in square brackets, and values may be either unquoted       - in which case they may not contain spaces - or single-quoted. Single quotes in      a quoted value may be backslash-escaped.                                       \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510                                       \\u2502 \\u250c\\u2500\\u2500\\u2500\\u2510  \\u2502        \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2524\\\" \\\"\\u2502\\u25c4\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510        \\u2502                                \\u2514\\u2500\\u2500\\u2500\\u2518                                           \\u2502        \\u2502  \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510 \\u2502      ^\\u2500\\u2534\\u2500\\u25ba\\u2502key\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"[\\\"\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502arg\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502\\\"]\\\"\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"=\\\"\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"'\\\"\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502quoted_value\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502\\\"'\\\"\\u251c\\u2500\\u253c\\u2500$           \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502                 \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518        \\u2502          \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510         \\u2502                                                     \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u25ba\\u2502unquoted_value\\u251c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518                                                                \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518      Record types:       - a[<coinType>] - Specifies how an `addr()` request should be resolved for the specified         `coinType`. Ethereum has `coinType` 60. The value must be 0x-prefixed hexadecimal, and will         be returned unmodified; this means that non-EVM addresses will need to be translated         into binary format and then encoded in hex.         Examples:          - a[60]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7          - a[0]=0x00149010587f8364b964fcaa70687216b53bd2cbd798       - a[e<chainId>] - Specifies how an `addr()` request should be resolved for the specified         `chainId`. The value must be 0x-prefixed hexadecimal. When encoding an address for an         EVM-based cryptocurrency that uses a chainId instead of a coinType, this syntax *must*         be used in place of the coin type - eg, Optimism is `a[e10]`, not `a[2147483658]`.         A list of supported cryptocurrencies for both syntaxes can be found here:           https://github.com/ensdomains/address-encoder/blob/master/docs/supported-cryptocurrencies.md         Example:          - a[e10]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7       - t[<key>] - Specifies how a `text()` request should be resolved for the specified `key`.         Examples:          - t[com.twitter]=nicksdjohnson          - t[url]='https://ens.domains/'          - t[note]='I\\\\'m great'\",\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/resolvers/profiles/ExtendedDNSResolver.sol\":\"ExtendedDNSResolver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n    uint8 private constant _ADDRESS_LENGTH = 20;\\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), _SYMBOLS))\\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 toString(int256 value) internal pure returns (string memory) {\\n        return string(abi.encodePacked(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        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] = _SYMBOLS[value & 0xf];\\n            value >>= 4;\\n        }\\n        require(value == 0, \\\"Strings: hex length insufficient\\\");\\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 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 keccak256(bytes(a)) == keccak256(bytes(b));\\n    }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n    enum Rounding {\\n        Down, // Toward negative infinity\\n        Up, // Toward infinity\\n        Zero // Toward zero\\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 up instead\\n     * of rounding down.\\n     */\\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\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 denominator == 0\\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n     * with further edits by 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; // 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                prod0 := mul(x, y)\\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            require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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. Always >= 1.\\n            // See https://cs.stackexchange.com/q/138556/92363.\\n\\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\\n            uint256 twos = denominator & (~denominator + 1);\\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 works\\n            // 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 (rounding == Rounding.Up && 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 down.\\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        // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n        // \\u2192 `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 + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 2, rounded down, of a positive value.\\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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 10, rounded down, of a positive value.\\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 + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 256, rounded down, of a positive value.\\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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\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\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/ExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"../../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport \\\"../../resolvers/profiles/IAddressResolver.sol\\\";\\nimport \\\"../../resolvers/profiles/IAddrResolver.sol\\\";\\nimport \\\"../../resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"../../utils/HexUtils.sol\\\";\\nimport \\\"../../utils/BytesUtils.sol\\\";\\n\\n/**\\n * @dev Resolves names on ENS by interpreting record data stored in a DNS TXT record.\\n *      This resolver implements the IExtendedDNSResolver interface, meaning that when\\n *      a DNS name specifies it as the resolver via a TXT record, this resolver's\\n *      resolve() method is invoked, and is passed any additional information from that\\n *      text record. This resolver implements a simple text parser allowing a variety\\n *      of records to be specified in text, which will then be used to resolve the name\\n *      in ENS.\\n *\\n *      To use this, set a TXT record on your DNS name in the following format:\\n *          ENS1 <address or name of ExtendedDNSResolver> <record data>\\n *\\n *      For example:\\n *          ENS1 2.dnsname.ens.eth a[60]=0x1234...\\n *\\n *      The record data consists of a series of key=value pairs, separated by spaces. Keys\\n *      may have an optional argument in square brackets, and values may be either unquoted\\n *       - in which case they may not contain spaces - or single-quoted. Single quotes in\\n *      a quoted value may be backslash-escaped.\\n *\\n *\\n *                                       \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n *                                       \\u2502 \\u250c\\u2500\\u2500\\u2500\\u2510  \\u2502\\n *        \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2524\\\" \\\"\\u2502\\u25c4\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n *        \\u2502                                \\u2514\\u2500\\u2500\\u2500\\u2518                                           \\u2502\\n *        \\u2502  \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510    \\u250c\\u2500\\u2500\\u2500\\u2510 \\u2502\\n *      ^\\u2500\\u2534\\u2500\\u25ba\\u2502key\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"[\\\"\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502arg\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502\\\"]\\\"\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"=\\\"\\u251c\\u2500\\u252c\\u2500\\u25ba\\u2502\\\"'\\\"\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502quoted_value\\u251c\\u2500\\u2500\\u2500\\u25ba\\u2502\\\"'\\\"\\u251c\\u2500\\u253c\\u2500$\\n *           \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502  \\u2514\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518    \\u2514\\u2500\\u2500\\u2500\\u2518 \\u2502\\n *                 \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518        \\u2502          \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510         \\u2502\\n *                                                     \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u25ba\\u2502unquoted_value\\u251c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n *                                                                \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n *\\n *      Record types:\\n *       - a[<coinType>] - Specifies how an `addr()` request should be resolved for the specified\\n *         `coinType`. Ethereum has `coinType` 60. The value must be 0x-prefixed hexadecimal, and will\\n *         be returned unmodified; this means that non-EVM addresses will need to be translated\\n *         into binary format and then encoded in hex.\\n *         Examples:\\n *          - a[60]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7\\n *          - a[0]=0x00149010587f8364b964fcaa70687216b53bd2cbd798\\n *       - a[e<chainId>] - Specifies how an `addr()` request should be resolved for the specified\\n *         `chainId`. The value must be 0x-prefixed hexadecimal. When encoding an address for an\\n *         EVM-based cryptocurrency that uses a chainId instead of a coinType, this syntax *must*\\n *         be used in place of the coin type - eg, Optimism is `a[e10]`, not `a[2147483658]`.\\n *         A list of supported cryptocurrencies for both syntaxes can be found here:\\n *           https://github.com/ensdomains/address-encoder/blob/master/docs/supported-cryptocurrencies.md\\n *         Example:\\n *          - a[e10]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7\\n *       - t[<key>] - Specifies how a `text()` request should be resolved for the specified `key`.\\n *         Examples:\\n *          - t[com.twitter]=nicksdjohnson\\n *          - t[url]='https://ens.domains/'\\n *          - t[note]='I\\\\'m great'\\n */\\ncontract ExtendedDNSResolver is IExtendedDNSResolver, IERC165 {\\n    using HexUtils for *;\\n    using BytesUtils for *;\\n    using Strings for *;\\n\\n    uint256 private constant COIN_TYPE_ETH = 60;\\n\\n    error NotImplemented();\\n    error InvalidAddressFormat(bytes addr);\\n\\n    function supportsInterface(\\n        bytes4 interfaceId\\n    ) external view virtual override returns (bool) {\\n        return interfaceId == type(IExtendedDNSResolver).interfaceId;\\n    }\\n\\n    function resolve(\\n        bytes calldata /* name */,\\n        bytes calldata data,\\n        bytes calldata context\\n    ) external pure override returns (bytes memory) {\\n        bytes4 selector = bytes4(data);\\n        if (selector == IAddrResolver.addr.selector) {\\n            return _resolveAddr(context);\\n        } else if (selector == IAddressResolver.addr.selector) {\\n            return _resolveAddress(data, context);\\n        } else if (selector == ITextResolver.text.selector) {\\n            return _resolveText(data, context);\\n        }\\n        revert NotImplemented();\\n    }\\n\\n    function _resolveAddress(\\n        bytes calldata data,\\n        bytes calldata context\\n    ) internal pure returns (bytes memory) {\\n        (, uint256 coinType) = abi.decode(data[4:], (bytes32, uint256));\\n        bytes memory value;\\n        // Per https://docs.ens.domains/ensip/11#specification\\n        if (coinType & 0x80000000 != 0) {\\n            value = _findValue(\\n                context,\\n                bytes.concat(\\n                    \\\"a[e\\\",\\n                    bytes((coinType & 0x7fffffff).toString()),\\n                    \\\"]=\\\"\\n                )\\n            );\\n        } else {\\n            value = _findValue(\\n                context,\\n                bytes.concat(\\\"a[\\\", bytes(coinType.toString()), \\\"]=\\\")\\n            );\\n        }\\n        if (value.length == 0) {\\n            return value;\\n        }\\n        (bytes memory record, bool valid) = value.hexToBytes(2, value.length);\\n        if (!valid) revert InvalidAddressFormat(value);\\n        return record;\\n    }\\n\\n    function _resolveAddr(\\n        bytes calldata context\\n    ) internal pure returns (bytes memory) {\\n        bytes memory value = _findValue(context, \\\"a[60]=\\\");\\n        if (value.length == 0) {\\n            return value;\\n        }\\n        (bytes memory record, bool valid) = value.hexToBytes(2, value.length);\\n        if (!valid) revert InvalidAddressFormat(value);\\n        return record;\\n    }\\n\\n    function _resolveText(\\n        bytes calldata data,\\n        bytes calldata context\\n    ) internal pure returns (bytes memory) {\\n        (, string memory key) = abi.decode(data[4:], (bytes32, string));\\n        bytes memory value = _findValue(\\n            context,\\n            bytes.concat(\\\"t[\\\", bytes(key), \\\"]=\\\")\\n        );\\n        return value;\\n    }\\n\\n    uint256 constant STATE_START = 0;\\n    uint256 constant STATE_IGNORED_KEY = 1;\\n    uint256 constant STATE_IGNORED_KEY_ARG = 2;\\n    uint256 constant STATE_VALUE = 3;\\n    uint256 constant STATE_QUOTED_VALUE = 4;\\n    uint256 constant STATE_UNQUOTED_VALUE = 5;\\n    uint256 constant STATE_IGNORED_VALUE = 6;\\n    uint256 constant STATE_IGNORED_QUOTED_VALUE = 7;\\n    uint256 constant STATE_IGNORED_UNQUOTED_VALUE = 8;\\n\\n    /**\\n     * @dev Implements a DFA to parse the text record, looking for an entry\\n     *      matching `key`.\\n     * @param data The text record to parse.\\n     * @param key The exact key to search for.\\n     * @return value The value if found, or an empty string if `key` does not exist.\\n     */\\n    function _findValue(\\n        bytes memory data,\\n        bytes memory key\\n    ) internal pure returns (bytes memory value) {\\n        // Here we use a simple state machine to parse the text record. We\\n        // process characters one at a time; each character can trigger a\\n        // transition to a new state, or terminate the DFA and return a value.\\n        // For states that expect to process a number of tokens, we use\\n        // inner loops for efficiency reasons, to avoid the need to go\\n        // through the outer loop and switch statement for every character.\\n        uint256 state = STATE_START;\\n        uint256 len = data.length;\\n        for (uint256 i = 0; i < len; ) {\\n            if (state == STATE_START) {\\n                // Look for a matching key.\\n                if (data.equals(i, key, 0, key.length)) {\\n                    i += key.length;\\n                    state = STATE_VALUE;\\n                } else {\\n                    state = STATE_IGNORED_KEY;\\n                }\\n            } else if (state == STATE_IGNORED_KEY) {\\n                for (; i < len; i++) {\\n                    if (data[i] == \\\"=\\\") {\\n                        state = STATE_IGNORED_VALUE;\\n                        i += 1;\\n                        break;\\n                    } else if (data[i] == \\\"[\\\") {\\n                        state = STATE_IGNORED_KEY_ARG;\\n                        i += 1;\\n                        break;\\n                    }\\n                }\\n            } else if (state == STATE_IGNORED_KEY_ARG) {\\n                for (; i < len; i++) {\\n                    if (data[i] == \\\"]\\\") {\\n                        state = STATE_IGNORED_VALUE;\\n                        i += 1;\\n                        if (data[i] == \\\"=\\\") {\\n                            i += 1;\\n                        }\\n                        break;\\n                    }\\n                }\\n            } else if (state == STATE_VALUE) {\\n                if (data[i] == \\\"'\\\") {\\n                    state = STATE_QUOTED_VALUE;\\n                    i += 1;\\n                } else {\\n                    state = STATE_UNQUOTED_VALUE;\\n                }\\n            } else if (state == STATE_QUOTED_VALUE) {\\n                uint256 start = i;\\n                uint256 valueLen = 0;\\n                bool escaped = false;\\n                for (; i < len; i++) {\\n                    if (escaped) {\\n                        data[start + valueLen] = data[i];\\n                        valueLen += 1;\\n                        escaped = false;\\n                    } else {\\n                        if (data[i] == \\\"\\\\\\\\\\\") {\\n                            escaped = true;\\n                        } else if (data[i] == \\\"'\\\") {\\n                            return data.substring(start, valueLen);\\n                        } else {\\n                            data[start + valueLen] = data[i];\\n                            valueLen += 1;\\n                        }\\n                    }\\n                }\\n            } else if (state == STATE_UNQUOTED_VALUE) {\\n                uint256 start = i;\\n                for (; i < len; i++) {\\n                    if (data[i] == \\\" \\\") {\\n                        return data.substring(start, i - start);\\n                    }\\n                }\\n                return data.substring(start, len - start);\\n            } else if (state == STATE_IGNORED_VALUE) {\\n                if (data[i] == \\\"'\\\") {\\n                    state = STATE_IGNORED_QUOTED_VALUE;\\n                    i += 1;\\n                } else {\\n                    state = STATE_IGNORED_UNQUOTED_VALUE;\\n                }\\n            } else if (state == STATE_IGNORED_QUOTED_VALUE) {\\n                bool escaped = false;\\n                for (; i < len; i++) {\\n                    if (escaped) {\\n                        escaped = false;\\n                    } else {\\n                        if (data[i] == \\\"\\\\\\\\\\\") {\\n                            escaped = true;\\n                        } else if (data[i] == \\\"'\\\") {\\n                            i += 1;\\n                            while (data[i] == \\\" \\\") {\\n                                i += 1;\\n                            }\\n                            state = STATE_START;\\n                            break;\\n                        }\\n                    }\\n                }\\n            } else {\\n                assert(state == STATE_IGNORED_UNQUOTED_VALUE);\\n                for (; i < len; i++) {\\n                    if (data[i] == \\\" \\\") {\\n                        while (data[i] == \\\" \\\") {\\n                            i += 1;\\n                        }\\n                        state = STATE_START;\\n                        break;\\n                    }\\n                }\\n            }\\n        }\\n        return \\\"\\\";\\n    }\\n}\\n\",\"keccak256\":\"0xb8954b152d8fb29cd7239e33d0c17c3dfb52ff7cd6d4c060bb72e62b0ae8e197\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the legacy (ETH-only) addr function.\\n */\\ninterface IAddrResolver {\\n    event AddrChanged(bytes32 indexed node, address a);\\n\\n    /**\\n     * Returns the address associated with an ENS node.\\n     * @param node The ENS node to query.\\n     * @return The associated address.\\n     */\\n    function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x2ad7f2fc60ebe0f93745fe70247f6a854f66af732483fda2a3c5e055614445e8\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the new (multicoin) addr function.\\n */\\ninterface IAddressResolver {\\n    event AddressChanged(\\n        bytes32 indexed node,\\n        uint256 coinType,\\n        bytes newAddress\\n    );\\n\\n    function addr(\\n        bytes32 node,\\n        uint256 coinType\\n    ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x411447c1e90c51e09702815a85ec725ffbbe37cf96e8cc4d2a8bd4ad8a59d73e\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n    function resolve(\\n        bytes memory name,\\n        bytes memory data,\\n        bytes memory context\\n    ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n    event TextChanged(\\n        bytes32 indexed node,\\n        string indexed indexedKey,\\n        string key,\\n        string value\\n    );\\n\\n    /**\\n     * Returns the text data associated with an ENS node and key.\\n     * @param node The ENS node to query.\\n     * @param key The text data key to query.\\n     * @return The associated text data.\\n     */\\n    function text(\\n        bytes32 node,\\n        string calldata key\\n    ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x7c5debb3c42cd9f5de2274ea7aa053f238608314b62db441c40e31cea2543fd5\",\"license\":\"MIT\"},\"contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n    error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n    /*\\n     * @dev Returns the keccak-256 hash of a byte range.\\n     * @param self The byte string to hash.\\n     * @param offset The position to start hashing at.\\n     * @param len The number of bytes to hash.\\n     * @return The hash of the byte range.\\n     */\\n    function keccak(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        require(offset + len <= self.length);\\n        assembly {\\n            ret := keccak256(add(add(self, 32), offset), len)\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the ENS namehash of a DNS-encoded name.\\n     * @param self The DNS-encoded name to hash.\\n     * @param offset The offset at which to start hashing.\\n     * @return The namehash of the name.\\n     */\\n    function namehash(\\n        bytes memory self,\\n        uint256 offset\\n    ) internal pure returns (bytes32) {\\n        (bytes32 labelhash, uint256 newOffset) = readLabel(self, offset);\\n        if (labelhash == bytes32(0)) {\\n            require(offset == self.length - 1, \\\"namehash: Junk at end of name\\\");\\n            return bytes32(0);\\n        }\\n        return\\n            keccak256(abi.encodePacked(namehash(self, newOffset), labelhash));\\n    }\\n\\n    /**\\n     * @dev Returns the keccak-256 hash of a DNS-encoded label, and the offset to the start of the next label.\\n     * @param self The byte string to read a label from.\\n     * @param idx The index to read a label at.\\n     * @return labelhash The hash of the label at the specified index, or 0 if it is the last label.\\n     * @return newIdx The index of the start of the next label.\\n     */\\n    function readLabel(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (bytes32 labelhash, uint256 newIdx) {\\n        require(idx < self.length, \\\"readLabel: Index out of bounds\\\");\\n        uint256 len = uint256(uint8(self[idx]));\\n        if (len > 0) {\\n            labelhash = keccak(self, idx + 1, len);\\n        } else {\\n            labelhash = bytes32(0);\\n        }\\n        newIdx = idx + len + 1;\\n    }\\n\\n    /*\\n     * @dev Returns a positive number if `other` comes lexicographically after\\n     *      `self`, a negative number if it comes before, or zero if the\\n     *      contents of the two bytes are equal.\\n     * @param self The first bytes to compare.\\n     * @param other The second bytes to compare.\\n     * @return The result of the comparison.\\n     */\\n    function compare(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (int256) {\\n        return compare(self, 0, self.length, other, 0, other.length);\\n    }\\n\\n    /*\\n     * @dev Returns a positive number if `other` comes lexicographically after\\n     *      `self`, a negative number if it comes before, or zero if the\\n     *      contents of the two bytes are equal. Comparison is done per-rune,\\n     *      on unicode codepoints.\\n     * @param self The first bytes to compare.\\n     * @param offset The offset of self.\\n     * @param len    The length of self.\\n     * @param other The second bytes to compare.\\n     * @param otheroffset The offset of the other string.\\n     * @param otherlen    The length of the other string.\\n     * @return The result of the comparison.\\n     */\\n    function compare(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len,\\n        bytes memory other,\\n        uint256 otheroffset,\\n        uint256 otherlen\\n    ) internal pure returns (int256) {\\n        if (offset + len > self.length) {\\n            revert OffsetOutOfBoundsError(offset + len, self.length);\\n        }\\n        if (otheroffset + otherlen > other.length) {\\n            revert OffsetOutOfBoundsError(otheroffset + otherlen, other.length);\\n        }\\n\\n        uint256 shortest = len;\\n        if (otherlen < len) shortest = otherlen;\\n\\n        uint256 selfptr;\\n        uint256 otherptr;\\n\\n        assembly {\\n            selfptr := add(self, add(offset, 32))\\n            otherptr := add(other, add(otheroffset, 32))\\n        }\\n        for (uint256 idx = 0; idx < shortest; idx += 32) {\\n            uint256 a;\\n            uint256 b;\\n            assembly {\\n                a := mload(selfptr)\\n                b := mload(otherptr)\\n            }\\n            if (a != b) {\\n                // Mask out irrelevant bytes and check again\\n                uint256 mask;\\n                if (shortest - idx >= 32) {\\n                    mask = type(uint256).max;\\n                } else {\\n                    mask = ~(2 ** (8 * (idx + 32 - shortest)) - 1);\\n                }\\n                int256 diff = int256(a & mask) - int256(b & mask);\\n                if (diff != 0) return diff;\\n            }\\n            selfptr += 32;\\n            otherptr += 32;\\n        }\\n\\n        return int256(len) - int256(otherlen);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @param otherOffset The offset into the second byte range.\\n     * @param len The number of bytes to compare\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other,\\n        uint256 otherOffset,\\n        uint256 len\\n    ) internal pure returns (bool) {\\n        return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal with offsets.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @param otherOffset The offset into the second byte range.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other,\\n        uint256 otherOffset\\n    ) internal pure returns (bool) {\\n        return\\n            keccak(self, offset, self.length - offset) ==\\n            keccak(other, otherOffset, other.length - otherOffset);\\n    }\\n\\n    /*\\n     * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n     *      they are equal.\\n     * @param self The first byte range to compare.\\n     * @param offset The offset into the first byte range.\\n     * @param other The second byte range to compare.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        uint256 offset,\\n        bytes memory other\\n    ) internal pure returns (bool) {\\n        return\\n            self.length == offset + other.length &&\\n            equals(self, offset, other, 0, other.length);\\n    }\\n\\n    /*\\n     * @dev Returns true if the two byte ranges are equal.\\n     * @param self The first byte range to compare.\\n     * @param other The second byte range to compare.\\n     * @return True if the byte ranges are equal, false otherwise.\\n     */\\n    function equals(\\n        bytes memory self,\\n        bytes memory other\\n    ) internal pure returns (bool) {\\n        return\\n            self.length == other.length &&\\n            equals(self, 0, other, 0, self.length);\\n    }\\n\\n    /*\\n     * @dev Returns the 8-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 8 bits of the string, interpreted as an integer.\\n     */\\n    function readUint8(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint8 ret) {\\n        return uint8(self[idx]);\\n    }\\n\\n    /*\\n     * @dev Returns the 16-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 16 bits of the string, interpreted as an integer.\\n     */\\n    function readUint16(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint16 ret) {\\n        require(idx + 2 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32-bit number at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bits of the string, interpreted as an integer.\\n     */\\n    function readUint32(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (uint32 ret) {\\n        require(idx + 4 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32 byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytes32(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (bytes32 ret) {\\n        require(idx + 32 <= self.length);\\n        assembly {\\n            ret := mload(add(add(self, 32), idx))\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the 32 byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytes20(\\n        bytes memory self,\\n        uint256 idx\\n    ) internal pure returns (bytes20 ret) {\\n        require(idx + 20 <= self.length);\\n        assembly {\\n            ret := and(\\n                mload(add(add(self, 32), idx)),\\n                0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000\\n            )\\n        }\\n    }\\n\\n    /*\\n     * @dev Returns the n byte value at the specified index of self.\\n     * @param self The byte string.\\n     * @param idx The index into the bytes.\\n     * @param len The number of bytes.\\n     * @return The specified 32 bytes of the string.\\n     */\\n    function readBytesN(\\n        bytes memory self,\\n        uint256 idx,\\n        uint256 len\\n    ) internal pure returns (bytes32 ret) {\\n        require(len <= 32);\\n        require(idx + len <= self.length);\\n        assembly {\\n            let mask := not(sub(exp(256, sub(32, len)), 1))\\n            ret := and(mload(add(add(self, 32), idx)), mask)\\n        }\\n    }\\n\\n    function memcpy(uint256 dest, uint256 src, uint256 len) private pure {\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint256 mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n    }\\n\\n    /*\\n     * @dev Copies a substring into a new byte string.\\n     * @param self The byte string to copy from.\\n     * @param offset The offset to start copying at.\\n     * @param len The number of bytes to copy.\\n     */\\n    function substring(\\n        bytes memory self,\\n        uint256 offset,\\n        uint256 len\\n    ) internal pure returns (bytes memory) {\\n        require(offset + len <= self.length);\\n\\n        bytes memory ret = new bytes(len);\\n        uint256 dest;\\n        uint256 src;\\n\\n        assembly {\\n            dest := add(ret, 32)\\n            src := add(add(self, 32), offset)\\n        }\\n        memcpy(dest, src, len);\\n\\n        return ret;\\n    }\\n\\n    // Maps characters from 0x30 to 0x7A to their base32 values.\\n    // 0xFF represents invalid characters in that range.\\n    bytes constant base32HexTable =\\n        hex\\\"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\\\";\\n\\n    /**\\n     * @dev Decodes unpadded base32 data of up to one word in length.\\n     * @param self The data to decode.\\n     * @param off Offset into the string to start at.\\n     * @param len Number of characters to decode.\\n     * @return The decoded data, left aligned.\\n     */\\n    function base32HexDecodeWord(\\n        bytes memory self,\\n        uint256 off,\\n        uint256 len\\n    ) internal pure returns (bytes32) {\\n        require(len <= 52);\\n\\n        uint256 ret = 0;\\n        uint8 decoded;\\n        for (uint256 i = 0; i < len; i++) {\\n            bytes1 char = self[off + i];\\n            require(char >= 0x30 && char <= 0x7A);\\n            decoded = uint8(base32HexTable[uint256(uint8(char)) - 0x30]);\\n            require(decoded <= 0x20);\\n            if (i == len - 1) {\\n                break;\\n            }\\n            ret = (ret << 5) | decoded;\\n        }\\n\\n        uint256 bitlen = len * 5;\\n        if (len % 8 == 0) {\\n            // Multiple of 8 characters, no padding\\n            ret = (ret << 5) | decoded;\\n        } else if (len % 8 == 2) {\\n            // Two extra characters - 1 byte\\n            ret = (ret << 3) | (decoded >> 2);\\n            bitlen -= 2;\\n        } else if (len % 8 == 4) {\\n            // Four extra characters - 2 bytes\\n            ret = (ret << 1) | (decoded >> 4);\\n            bitlen -= 4;\\n        } else if (len % 8 == 5) {\\n            // Five extra characters - 3 bytes\\n            ret = (ret << 4) | (decoded >> 1);\\n            bitlen -= 1;\\n        } else if (len % 8 == 7) {\\n            // Seven extra characters - 4 bytes\\n            ret = (ret << 2) | (decoded >> 3);\\n            bitlen -= 3;\\n        } else {\\n            revert();\\n        }\\n\\n        return bytes32(ret << (256 - bitlen));\\n    }\\n\\n    /**\\n     * @dev Finds the first occurrence of the byte `needle` in `self`.\\n     * @param self The string to search\\n     * @param off The offset to start searching at\\n     * @param len The number of bytes to search\\n     * @param needle The byte to search for\\n     * @return The offset of `needle` in `self`, or 2**256-1 if it was not found.\\n     */\\n    function find(\\n        bytes memory self,\\n        uint256 off,\\n        uint256 len,\\n        bytes1 needle\\n    ) internal pure returns (uint256) {\\n        for (uint256 idx = off; idx < off + len; idx++) {\\n            if (self[idx] == needle) {\\n                return idx;\\n            }\\n        }\\n        return type(uint256).max;\\n    }\\n}\\n\",\"keccak256\":\"0xc566a3569af880a096a9bfb2fbb77060ef7aecde1a205dc26446a58877412060\",\"license\":\"MIT\"},\"contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n    /**\\n     * @dev Attempts to parse bytes32 from a hex string\\n     * @param str The string to parse\\n     * @param idx The offset to start parsing at\\n     * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n     */\\n    function hexStringToBytes32(\\n        bytes memory str,\\n        uint256 idx,\\n        uint256 lastIdx\\n    ) internal pure returns (bytes32, bool) {\\n        require(lastIdx - idx <= 64);\\n        (bytes memory r, bool valid) = hexToBytes(str, idx, lastIdx);\\n        if (!valid) {\\n            return (bytes32(0), false);\\n        }\\n        bytes32 ret;\\n        assembly {\\n            ret := shr(mul(4, sub(64, sub(lastIdx, idx))), mload(add(r, 32)))\\n        }\\n        return (ret, true);\\n    }\\n\\n    function hexToBytes(\\n        bytes memory str,\\n        uint256 idx,\\n        uint256 lastIdx\\n    ) internal pure returns (bytes memory r, bool valid) {\\n        uint256 hexLength = lastIdx - idx;\\n        if (hexLength % 2 == 1) {\\n            revert(\\\"Invalid string length\\\");\\n        }\\n        r = new bytes(hexLength / 2);\\n        valid = true;\\n        assembly {\\n            // check that the index to read to is not past the end of the string\\n            if gt(lastIdx, mload(str)) {\\n                revert(0, 0)\\n            }\\n\\n            function getHex(c) -> ascii {\\n                // chars 48-57: 0-9\\n                if and(gt(c, 47), lt(c, 58)) {\\n                    ascii := sub(c, 48)\\n                    leave\\n                }\\n                // chars 65-70: A-F\\n                if and(gt(c, 64), lt(c, 71)) {\\n                    ascii := add(sub(c, 65), 10)\\n                    leave\\n                }\\n                // chars 97-102: a-f\\n                if and(gt(c, 96), lt(c, 103)) {\\n                    ascii := add(sub(c, 97), 10)\\n                    leave\\n                }\\n                // invalid char\\n                ascii := 0xff\\n            }\\n\\n            let ptr := add(str, 32)\\n            for {\\n                let i := idx\\n            } lt(i, lastIdx) {\\n                i := add(i, 2)\\n            } {\\n                let byte1 := getHex(byte(0, mload(add(ptr, i))))\\n                let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))\\n                // if either byte is invalid, set invalid and break loop\\n                if or(eq(byte1, 0xff), eq(byte2, 0xff)) {\\n                    valid := false\\n                    break\\n                }\\n                let combined := or(shl(4, byte1), byte2)\\n                mstore8(add(add(r, 32), div(sub(i, idx), 2)), combined)\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @dev Attempts to parse an address from a hex string\\n     * @param str The string to parse\\n     * @param idx The offset to start parsing at\\n     * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n     */\\n    function hexToAddress(\\n        bytes memory str,\\n        uint256 idx,\\n        uint256 lastIdx\\n    ) internal pure returns (address, bool) {\\n        if (lastIdx - idx < 40) return (address(0x0), false);\\n        (bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);\\n        return (address(uint160(uint256(r))), valid);\\n    }\\n\\n    /**\\n     * @dev Attempts to convert an address to a hex string\\n     * @param addr The _addr to parse\\n     */\\n    function addressToHex(address addr) internal pure returns (string memory) {\\n        bytes memory hexString = new bytes(40);\\n        for (uint i = 0; i < 20; i++) {\\n            bytes1 byteValue = bytes1(uint8(uint160(addr) >> (8 * (19 - i))));\\n            bytes1 highNibble = bytes1(uint8(byteValue) / 16);\\n            bytes1 lowNibble = bytes1(\\n                uint8(byteValue) - 16 * uint8(highNibble)\\n            );\\n            hexString[2 * i] = _nibbleToHexChar(highNibble);\\n            hexString[2 * i + 1] = _nibbleToHexChar(lowNibble);\\n        }\\n        return string(hexString);\\n    }\\n\\n    function _nibbleToHexChar(\\n        bytes1 nibble\\n    ) internal pure returns (bytes1 hexChar) {\\n        if (uint8(nibble) < 10) return bytes1(uint8(nibble) + 0x30);\\n        else return bytes1(uint8(nibble) + 0x57);\\n    }\\n}\\n\",\"keccak256\":\"0xd6a9ab6d19632f634ee0f29173278fb4ba1d90fbbb470e779d76f278a8a2b90d\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b5061134e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780638ef98a7e1461008d575b600080fd5b610078610049366004610ec7565b6001600160e01b0319167f8ef98a7e000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6100a061009b366004610f41565b6100ad565b6040516100849190610fff565b606060006100bb8587611032565b90507fc4c4a822000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610100576100f884846101b6565b9150506101ac565b7f0e3481fa000000000000000000000000000000000000000000000000000000006001600160e01b031982160161013d576100f886868686610292565b7fa62e2bc4000000000000000000000000000000000000000000000000000000006001600160e01b031982160161017a576100f8868686866103ed565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9695505050505050565b6060600061022e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600681527f615b36305d3d0000000000000000000000000000000000000000000000000000602082015291506104659050565b9050805160000361024057905061028c565b60008061025a6002845185610a7e9092919063ffffffff16565b91509150806102875782604051630f79e00960e21b815260040161027e9190610fff565b60405180910390fd5b509150505b92915050565b606060006102a38560048189611062565b8101906102b0919061108c565b9150506060816380000000166000146103375761033085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030c92505050637fffffff8516610c26565b60405160200161031c91906110ae565b604051602081830303815290604052610465565b905061038f565b61038c85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037c9250869150610c269050565b60405160200161031c91906110ff565b90505b80516000036103a15791506103e59050565b6000806103bb6002845185610a7e9092919063ffffffff16565b91509150806103df5782604051630f79e00960e21b815260040161027e9190610fff565b50925050505b949350505050565b606060006103fe8560048189611062565b81019061040b9190611166565b915050600061045a85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060405161031c9250869150602001611221565b979650505050505050565b8151606090600090815b81811015610a6557826104b557845161049090879083908890600090610cc6565b156104ac5784516104a1908261126f565b90506003925061046f565b6001925061046f565b60018303610574575b8181101561056f578581815181106104d8576104d8611282565b01602001516001600160f81b031916603d60f81b03610507576006925061050060018261126f565b905061046f565b85818151811061051957610519611282565b01602001516001600160f81b0319167f5b000000000000000000000000000000000000000000000000000000000000000361055d576002925061050060018261126f565b8061056781611298565b9150506104be565b61046f565b60028303610625575b8181101561056f5785818151811061059757610597611282565b01602001516001600160f81b0319167f5d000000000000000000000000000000000000000000000000000000000000000361061357600692506105db60018261126f565b90508581815181106105ef576105ef611282565b01602001516001600160f81b031916603d60f81b0361056f5761050060018261126f565b8061061d81611298565b91505061057d565b600383036106705785818151811061063f5761063f611282565b01602001516001600160f81b031916602760f81b03610667576004925061050060018261126f565b6005925061046f565b6004830361081557806000805b8484101561080d57801561070c5788848151811061069d5761069d611282565b01602001516001600160f81b031916896106b7848661126f565b815181106106c7576106c7611282565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061070160018361126f565b9150600090506107fb565b88848151811061071e5761071e611282565b01602001516001600160f81b031916601760fa1b0361073f575060016107fb565b88848151811061075157610751611282565b01602001516001600160f81b031916602760f81b0361078257610775898484610ce9565b965050505050505061028c565b88848151811061079457610794611282565b01602001516001600160f81b031916896107ae848661126f565b815181106107be576107be611282565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506107f860018361126f565b91505b8361080581611298565b94505061067d565b50505061046f565b6005830361089357805b828210156108855786828151811061083957610839611282565b01602001516001600160f81b031916600160fd1b03610873576108688161086081856112b1565b899190610ce9565b94505050505061028c565b8161087d81611298565b92505061081f565b6108688161086081866112b1565b600683036108de578581815181106108ad576108ad611282565b01602001516001600160f81b031916602760f81b036108d5576007925061050060018261126f565b6008925061046f565b600783036109c95760005b828210156109c35780156108ff575060006109b1565b86828151811061091157610911611282565b01602001516001600160f81b031916601760fa1b03610932575060016109b1565b86828151811061094457610944611282565b01602001516001600160f81b031916602760f81b036109b15761096860018361126f565b91505b86828151811061097d5761097d611282565b01602001516001600160f81b031916600160fd1b036109a8576109a160018361126f565b915061096b565b600093506109c3565b816109bb81611298565b9250506108e9565b5061046f565b600883146109d9576109d96112c4565b8181101561056f578581815181106109f3576109f3611282565b01602001516001600160f81b031916600160fd1b03610a53575b858181518110610a1f57610a1f611282565b01602001516001600160f81b031916600160fd1b03610a4a57610a4360018261126f565b9050610a0d565b6000925061046f565b80610a5d81611298565b9150506109d9565b5050604080516020810190915260008152949350505050565b6060600080610a8d85856112b1565b9050610a9a6002826112f0565b600103610b03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e6774680000000000000000000000604482015260640161027e565b610b0e600282611304565b67ffffffffffffffff811115610b2657610b26611150565b6040519080825280601f01601f191660200182016040528015610b50576020820181803683370190505b509250600191508551841115610b6557600080fd5b610bb6565b6000603a8210602f83111615610b825750602f190190565b60478210604083111615610b9857506036190190565b60678210606083111615610bae57506056190190565b5060ff919050565b60208601855b85811015610c1b57610bd38183015160001a610b6a565b610be56001830184015160001a610b6a565b60ff811460ff83141715610bfe57600095505050610c1b565b60049190911b178060028984030487016020015350600201610bbc565b505050935093915050565b60606000610c3383610d6b565b600101905060008167ffffffffffffffff811115610c5357610c53611150565b6040519080825280601f01601f191660200182016040528015610c7d576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610c8757509392505050565b6000610cd3848484610e4d565b610cde878785610e4d565b149695505050505050565b8251606090610cf8838561126f565b1115610d0357600080fd5b60008267ffffffffffffffff811115610d1e57610d1e611150565b6040519080825280601f01601f191660200182016040528015610d48576020820181803683370190505b50905060208082019086860101610d60828287610e71565b509095945050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610db4577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310610de0576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610dfe57662386f26fc10000830492506010015b6305f5e1008310610e16576305f5e100830492506008015b6127108310610e2a57612710830492506004015b60648310610e3c576064830492506002015b600a831061028c5760010192915050565b8251600090610e5c838561126f565b1115610e6757600080fd5b5091016020012090565b60208110610ea95781518352610e8860208461126f565b9250610e9560208361126f565b9150610ea26020826112b1565b9050610e71565b905182516020929092036101000a6000190180199091169116179052565b600060208284031215610ed957600080fd5b81356001600160e01b031981168114610ef157600080fd5b9392505050565b60008083601f840112610f0a57600080fd5b50813567ffffffffffffffff811115610f2257600080fd5b602083019150836020828501011115610f3a57600080fd5b9250929050565b60008060008060008060608789031215610f5a57600080fd5b863567ffffffffffffffff80821115610f7257600080fd5b610f7e8a838b01610ef8565b90985096506020890135915080821115610f9757600080fd5b610fa38a838b01610ef8565b90965094506040890135915080821115610fbc57600080fd5b50610fc989828a01610ef8565b979a9699509497509295939492505050565b60005b83811015610ff6578181015183820152602001610fde565b50506000910152565b602081526000825180602084015261101e816040850160208701610fdb565b601f01601f19169190910160400192915050565b6001600160e01b0319813581811691600485101561105a5780818660040360031b1b83161692505b505092915050565b6000808585111561107257600080fd5b8386111561107f57600080fd5b5050820193919092039150565b6000806040838503121561109f57600080fd5b50508035926020909101359150565b7f615b6500000000000000000000000000000000000000000000000000000000008152600082516110e6816003850160208701610fdb565b615d3d60f01b6003939091019283015250600501919050565b7f615b000000000000000000000000000000000000000000000000000000000000815260008251611137816002850160208701610fdb565b615d3d60f01b6002939091019283015250600401919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561117957600080fd5b82359150602083013567ffffffffffffffff8082111561119857600080fd5b818501915085601f8301126111ac57600080fd5b8135818111156111be576111be611150565b604051601f8201601f19908116603f011681019083821181831017156111e6576111e6611150565b816040528281528860208487010111156111ff57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b7f745b000000000000000000000000000000000000000000000000000000000000815260008251611137816002850160208701610fdb565b634e487b7160e01b600052601160045260246000fd5b8082018082111561028c5761028c611259565b634e487b7160e01b600052603260045260246000fd5b6000600182016112aa576112aa611259565b5060010190565b8181038181111561028c5761028c611259565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826112ff576112ff6112da565b500690565b600082611313576113136112da565b50049056fea26469706673582212203572cfc5fcb1ebedbb66aca92142c81b01bd1363a5a1c1b46d18a861668d369764736f6c63430008110033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780638ef98a7e1461008d575b600080fd5b610078610049366004610ec7565b6001600160e01b0319167f8ef98a7e000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6100a061009b366004610f41565b6100ad565b6040516100849190610fff565b606060006100bb8587611032565b90507fc4c4a822000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610100576100f884846101b6565b9150506101ac565b7f0e3481fa000000000000000000000000000000000000000000000000000000006001600160e01b031982160161013d576100f886868686610292565b7fa62e2bc4000000000000000000000000000000000000000000000000000000006001600160e01b031982160161017a576100f8868686866103ed565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9695505050505050565b6060600061022e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600681527f615b36305d3d0000000000000000000000000000000000000000000000000000602082015291506104659050565b9050805160000361024057905061028c565b60008061025a6002845185610a7e9092919063ffffffff16565b91509150806102875782604051630f79e00960e21b815260040161027e9190610fff565b60405180910390fd5b509150505b92915050565b606060006102a38560048189611062565b8101906102b0919061108c565b9150506060816380000000166000146103375761033085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030c92505050637fffffff8516610c26565b60405160200161031c91906110ae565b604051602081830303815290604052610465565b905061038f565b61038c85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061037c9250869150610c269050565b60405160200161031c91906110ff565b90505b80516000036103a15791506103e59050565b6000806103bb6002845185610a7e9092919063ffffffff16565b91509150806103df5782604051630f79e00960e21b815260040161027e9190610fff565b50925050505b949350505050565b606060006103fe8560048189611062565b81019061040b9190611166565b915050600061045a85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060405161031c9250869150602001611221565b979650505050505050565b8151606090600090815b81811015610a6557826104b557845161049090879083908890600090610cc6565b156104ac5784516104a1908261126f565b90506003925061046f565b6001925061046f565b60018303610574575b8181101561056f578581815181106104d8576104d8611282565b01602001516001600160f81b031916603d60f81b03610507576006925061050060018261126f565b905061046f565b85818151811061051957610519611282565b01602001516001600160f81b0319167f5b000000000000000000000000000000000000000000000000000000000000000361055d576002925061050060018261126f565b8061056781611298565b9150506104be565b61046f565b60028303610625575b8181101561056f5785818151811061059757610597611282565b01602001516001600160f81b0319167f5d000000000000000000000000000000000000000000000000000000000000000361061357600692506105db60018261126f565b90508581815181106105ef576105ef611282565b01602001516001600160f81b031916603d60f81b0361056f5761050060018261126f565b8061061d81611298565b91505061057d565b600383036106705785818151811061063f5761063f611282565b01602001516001600160f81b031916602760f81b03610667576004925061050060018261126f565b6005925061046f565b6004830361081557806000805b8484101561080d57801561070c5788848151811061069d5761069d611282565b01602001516001600160f81b031916896106b7848661126f565b815181106106c7576106c7611282565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061070160018361126f565b9150600090506107fb565b88848151811061071e5761071e611282565b01602001516001600160f81b031916601760fa1b0361073f575060016107fb565b88848151811061075157610751611282565b01602001516001600160f81b031916602760f81b0361078257610775898484610ce9565b965050505050505061028c565b88848151811061079457610794611282565b01602001516001600160f81b031916896107ae848661126f565b815181106107be576107be611282565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506107f860018361126f565b91505b8361080581611298565b94505061067d565b50505061046f565b6005830361089357805b828210156108855786828151811061083957610839611282565b01602001516001600160f81b031916600160fd1b03610873576108688161086081856112b1565b899190610ce9565b94505050505061028c565b8161087d81611298565b92505061081f565b6108688161086081866112b1565b600683036108de578581815181106108ad576108ad611282565b01602001516001600160f81b031916602760f81b036108d5576007925061050060018261126f565b6008925061046f565b600783036109c95760005b828210156109c35780156108ff575060006109b1565b86828151811061091157610911611282565b01602001516001600160f81b031916601760fa1b03610932575060016109b1565b86828151811061094457610944611282565b01602001516001600160f81b031916602760f81b036109b15761096860018361126f565b91505b86828151811061097d5761097d611282565b01602001516001600160f81b031916600160fd1b036109a8576109a160018361126f565b915061096b565b600093506109c3565b816109bb81611298565b9250506108e9565b5061046f565b600883146109d9576109d96112c4565b8181101561056f578581815181106109f3576109f3611282565b01602001516001600160f81b031916600160fd1b03610a53575b858181518110610a1f57610a1f611282565b01602001516001600160f81b031916600160fd1b03610a4a57610a4360018261126f565b9050610a0d565b6000925061046f565b80610a5d81611298565b9150506109d9565b5050604080516020810190915260008152949350505050565b6060600080610a8d85856112b1565b9050610a9a6002826112f0565b600103610b03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e6774680000000000000000000000604482015260640161027e565b610b0e600282611304565b67ffffffffffffffff811115610b2657610b26611150565b6040519080825280601f01601f191660200182016040528015610b50576020820181803683370190505b509250600191508551841115610b6557600080fd5b610bb6565b6000603a8210602f83111615610b825750602f190190565b60478210604083111615610b9857506036190190565b60678210606083111615610bae57506056190190565b5060ff919050565b60208601855b85811015610c1b57610bd38183015160001a610b6a565b610be56001830184015160001a610b6a565b60ff811460ff83141715610bfe57600095505050610c1b565b60049190911b178060028984030487016020015350600201610bbc565b505050935093915050565b60606000610c3383610d6b565b600101905060008167ffffffffffffffff811115610c5357610c53611150565b6040519080825280601f01601f191660200182016040528015610c7d576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084610c8757509392505050565b6000610cd3848484610e4d565b610cde878785610e4d565b149695505050505050565b8251606090610cf8838561126f565b1115610d0357600080fd5b60008267ffffffffffffffff811115610d1e57610d1e611150565b6040519080825280601f01601f191660200182016040528015610d48576020820181803683370190505b50905060208082019086860101610d60828287610e71565b509095945050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310610db4577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310610de0576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310610dfe57662386f26fc10000830492506010015b6305f5e1008310610e16576305f5e100830492506008015b6127108310610e2a57612710830492506004015b60648310610e3c576064830492506002015b600a831061028c5760010192915050565b8251600090610e5c838561126f565b1115610e6757600080fd5b5091016020012090565b60208110610ea95781518352610e8860208461126f565b9250610e9560208361126f565b9150610ea26020826112b1565b9050610e71565b905182516020929092036101000a6000190180199091169116179052565b600060208284031215610ed957600080fd5b81356001600160e01b031981168114610ef157600080fd5b9392505050565b60008083601f840112610f0a57600080fd5b50813567ffffffffffffffff811115610f2257600080fd5b602083019150836020828501011115610f3a57600080fd5b9250929050565b60008060008060008060608789031215610f5a57600080fd5b863567ffffffffffffffff80821115610f7257600080fd5b610f7e8a838b01610ef8565b90985096506020890135915080821115610f9757600080fd5b610fa38a838b01610ef8565b90965094506040890135915080821115610fbc57600080fd5b50610fc989828a01610ef8565b979a9699509497509295939492505050565b60005b83811015610ff6578181015183820152602001610fde565b50506000910152565b602081526000825180602084015261101e816040850160208701610fdb565b601f01601f19169190910160400192915050565b6001600160e01b0319813581811691600485101561105a5780818660040360031b1b83161692505b505092915050565b6000808585111561107257600080fd5b8386111561107f57600080fd5b5050820193919092039150565b6000806040838503121561109f57600080fd5b50508035926020909101359150565b7f615b6500000000000000000000000000000000000000000000000000000000008152600082516110e6816003850160208701610fdb565b615d3d60f01b6003939091019283015250600501919050565b7f615b000000000000000000000000000000000000000000000000000000000000815260008251611137816002850160208701610fdb565b615d3d60f01b6002939091019283015250600401919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561117957600080fd5b82359150602083013567ffffffffffffffff8082111561119857600080fd5b818501915085601f8301126111ac57600080fd5b8135818111156111be576111be611150565b604051601f8201601f19908116603f011681019083821181831017156111e6576111e6611150565b816040528281528860208487010111156111ff57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b7f745b000000000000000000000000000000000000000000000000000000000000815260008251611137816002850160208701610fdb565b634e487b7160e01b600052601160045260246000fd5b8082018082111561028c5761028c611259565b634e487b7160e01b600052603260045260246000fd5b6000600182016112aa576112aa611259565b5060010190565b8181038181111561028c5761028c611259565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6000826112ff576112ff6112da565b500690565b600082611313576113136112da565b50049056fea26469706673582212203572cfc5fcb1ebedbb66aca92142c81b01bd1363a5a1c1b46d18a861668d369764736f6c63430008110033",
  "devdoc": {
    "details": "Resolves names on ENS by interpreting record data stored in a DNS TXT record.      This resolver implements the IExtendedDNSResolver interface, meaning that when      a DNS name specifies it as the resolver via a TXT record, this resolver's      resolve() method is invoked, and is passed any additional information from that      text record. This resolver implements a simple text parser allowing a variety      of records to be specified in text, which will then be used to resolve the name      in ENS.      To use this, set a TXT record on your DNS name in the following format:          ENS1 <address or name of ExtendedDNSResolver> <record data>      For example:          ENS1 2.dnsname.ens.eth a[60]=0x1234...      The record data consists of a series of key=value pairs, separated by spaces. Keys      may have an optional argument in square brackets, and values may be either unquoted       - in which case they may not contain spaces - or single-quoted. Single quotes in      a quoted value may be backslash-escaped.                                       ┌────────┐                                       │ ┌───┐  │        ┌──────────────────────────────┴─┤\" \"│◄─┴────────────────────────────────────────┐        │                                └───┘                                           │        │  ┌───┐    ┌───┐    ┌───┐    ┌───┐    ┌───┐    ┌───┐    ┌────────────┐    ┌───┐ │      ^─┴─►│key├─┬─►│\"[\"├───►│arg├───►│\"]\"├─┬─►│\"=\"├─┬─►│\"'\"├───►│quoted_value├───►│\"'\"├─┼─$           └───┘ │  └───┘    └───┘    └───┘ │  └───┘ │  └───┘    └────────────┘    └───┘ │                 └──────────────────────────┘        │          ┌──────────────┐         │                                                     └─────────►│unquoted_value├─────────┘                                                                └──────────────┘      Record types:       - a[<coinType>] - Specifies how an `addr()` request should be resolved for the specified         `coinType`. Ethereum has `coinType` 60. The value must be 0x-prefixed hexadecimal, and will         be returned unmodified; this means that non-EVM addresses will need to be translated         into binary format and then encoded in hex.         Examples:          - a[60]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7          - a[0]=0x00149010587f8364b964fcaa70687216b53bd2cbd798       - a[e<chainId>] - Specifies how an `addr()` request should be resolved for the specified         `chainId`. The value must be 0x-prefixed hexadecimal. When encoding an address for an         EVM-based cryptocurrency that uses a chainId instead of a coinType, this syntax *must*         be used in place of the coin type - eg, Optimism is `a[e10]`, not `a[2147483658]`.         A list of supported cryptocurrencies for both syntaxes can be found here:           https://github.com/ensdomains/address-encoder/blob/master/docs/supported-cryptocurrencies.md         Example:          - a[e10]=0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7       - t[<key>] - Specifies how a `text()` request should be resolved for the specified `key`.         Examples:          - t[com.twitter]=nicksdjohnson          - t[url]='https://ens.domains/'          - t[note]='I\\'m great'",
    "kind": "dev",
    "methods": {
      "supportsInterface(bytes4)": {
        "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas."
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [],
    "types": null
  }
}