From 2bf86e987b3350ee0075c9f2435e570f3911b957 Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:49:42 +0100 Subject: [PATCH] Default reverse resolver (#33) * Change ens-contracts to use default-reverse-resolver * Add suport for DefaultReverseResolver * Add hexToAddress to extract address * Add faulback to name function * Add fallback for text * Use imported IDefaultReverseResolver * Update bun.lockb and README * Update comment * Move DefaultReverseResolver * Add DefaultReverseResolver * Update bun.lockb * Add support for resolve on DefaultReverseResolver * Deployed new contracts * Add setdefaultname * Update README.md * Update README.md * Remove console.log * Point to default-reverse-resolver-2 * Reswitch to default-reverse-resolver * Update bun.ockb * Add whitespace * Check if invalid address * Override .text * Fix TypeError: ambiguous function error * Re-point to default-reverse-resolver * Added wait * Update storage location after removing Owner * Added wait on crosschain resolver * Use L2ReverseRevolver and fix broken test * Update ens-contracts branch * Eip 5559 support (#34) * Add IResolverSetter * Simplify metadata function * Fix failing tests * Add test for EIP 5559 * Added wait * Rename from IResolverSetter to IAddrSetter * Add resolveDeferral * Store chainId directly * Rename from resolveDeferral to setAddr --- README.md | 25 +- bun.lockb | Bin 640112 -> 615624 bytes crosschain-resolver/contracts/IAddrSetter.sol | 7 + .../contracts/IMetadataResolver.sol | 16 +- crosschain-resolver/contracts/L1Resolver.sol | 66 +- crosschain-resolver/contracts/deps.sol | 2 +- .../deploy_l1/10_l1resolver.ts | 5 +- crosschain-resolver/test/testResolver.ts | 49 +- crosschain-reverse-resolver/README.md | 59 +- .../contracts/DefaultReverseResolver.sol | 97 +++ .../contracts/IDefaultReverseResolver.sol | 10 + .../contracts/L1ReverseResolver.sol | 86 ++- .../contracts/deps.sol | 11 +- .../deploy_l1/01_defaultReverseResolver.ts | 16 + .../deploy_l1/10_l1resolver.ts | 9 +- .../sepolia/ArbL1ReverseResolver.json | 171 ++--- .../sepolia/BaseL1ReverseResolver.json | 171 ++--- .../sepolia/DefaultReverseResolver.json | 636 ++++++++++++++++++ .../sepolia/OpL1ReverseResolver.json | 171 ++--- .../1051d0da171e6c4c0eb815a27588fee5.json | 135 ++++ .../776c7519acf1eee16c4cde4c93293488.json | 102 +++ .../7cc7da1092d13c01f4d5f27229751af2.json | 150 +++++ crosschain-reverse-resolver/package.json | 1 + .../scripts/getname.ts | 25 +- .../scripts/setdefaultname.ts | 60 ++ .../scripts/setname.ts | 8 +- .../test/testReverseResolver.ts | 160 ++++- 27 files changed, 1742 insertions(+), 506 deletions(-) create mode 100644 crosschain-resolver/contracts/IAddrSetter.sol create mode 100644 crosschain-reverse-resolver/contracts/DefaultReverseResolver.sol create mode 100644 crosschain-reverse-resolver/contracts/IDefaultReverseResolver.sol create mode 100644 crosschain-reverse-resolver/deploy_l1/01_defaultReverseResolver.ts create mode 100644 crosschain-reverse-resolver/deployments/sepolia/DefaultReverseResolver.json create mode 100644 crosschain-reverse-resolver/deployments/sepolia/solcInputs/1051d0da171e6c4c0eb815a27588fee5.json create mode 100644 crosschain-reverse-resolver/deployments/sepolia/solcInputs/776c7519acf1eee16c4cde4c93293488.json create mode 100644 crosschain-reverse-resolver/deployments/sepolia/solcInputs/7cc7da1092d13c01f4d5f27229751af2.json create mode 100644 crosschain-reverse-resolver/scripts/setdefaultname.ts diff --git a/README.md b/README.md index 8142636f..75e3b10d 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,27 @@ This repository also contains the end-to-end tests for the entire stack. An instantiation of `evm-gateway` that targets Optimism. Combined with `op-verifier`, makes it possible for L1 contracts to fetch contract state data from Optimism. ### [op-verifier](/op-verifier/) -A complete Solidity library that facilitates sending CCIP-Read requests for Optimism state, and verifying the responses. \ No newline at end of file +A complete Solidity library that facilitates sending CCIP-Read requests for Optimism state, and verifying the responses. + + +## How to setup locally + +``` +gh repo clone ensdomains/evmgateway +bun install # `@ensdomains/@ensdomains` not found error will be thrown +bun run workspace evm-gateway build +bun install +bun run test +``` + +## Troubleshooting + +### Error HH12: Trying to use a non-local installation of Hardhat, which is not supported. + +`yarn test` spawns `hardhat test` in the forked process. When `hardhat` command is installed under the node_modules of under each workspace, it complains that it's using locally installed hardhat. Remove hardhat from local node_modules and make sure it's only installed under the root `node_modules` + +``` +rm -rf *-*/node_modules/hardhat +rm bun.lockb +bun install +``` \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 9f7d0e38aa65d278676ee1ecbf8831281553bb24..d29404047b3b8451abd27e3c9fac7fcd755c974b 100755 GIT binary patch delta 144554 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 h=GtcfKSqHadIXN-{{T-znL+>n delta 158796 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

CUoXGl#>GkYvrlEP54k4S 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 diff --git a/crosschain-resolver/contracts/IAddrSetter.sol b/crosschain-resolver/contracts/IAddrSetter.sol new file mode 100644 index 00000000..05e78ee9 --- /dev/null +++ b/crosschain-resolver/contracts/IAddrSetter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +interface IAddrSetter{ + function setAddr(bytes calldata name, address _addr) external view returns (bytes memory result); +} + diff --git a/crosschain-resolver/contracts/IMetadataResolver.sol b/crosschain-resolver/contracts/IMetadataResolver.sol index bcecbeb3..bf3a0fd0 100644 --- a/crosschain-resolver/contracts/IMetadataResolver.sol +++ b/crosschain-resolver/contracts/IMetadataResolver.sol @@ -6,27 +6,15 @@ interface IMetadataResolver { * @notice Get metadata about the CCIP Resolver ENSIP 16 https://docs.ens.domains/ens-improvement-proposals/ensip-16-offchain-metadata * @dev This function provides metadata about the CCIP Resolver, including its name, coin type, GraphQL URL, storage type, and encoded information. * @param name The domain name in format (dnsEncoded) - * @return coinType The cointype of the chain the target contract locates such as Optimism, Base, Arb, etc * @return graphqlUrl The GraphQL URL used by the resolver - * @return storageType 0 = EVM, 1 = Non blockchain, 2 = Starknet - * @return storageLocation The storage identifier. For EVM chains, this is the address of the resolver contract. - * @return context. An identifier used by l2 graph indexer for Domain schema id (`context-namehash`) allowing multiple resolver contracts to have own namespace. * */ function metadata(bytes calldata name) external view returns ( - uint256 coinType, - string memory graphqlUrl, - uint8 storageType, - bytes memory storageLocation, - bytes memory context + string memory graphqlUrl ); event MetadataChanged( bytes name, - uint256 coinType, - string graphqlUrl, - uint8 storageType, - bytes storageLocation, - bytes context + string graphqlUrl ); } \ No newline at end of file diff --git a/crosschain-resolver/contracts/L1Resolver.sol b/crosschain-resolver/contracts/L1Resolver.sol index 49c10aac..db6ff635 100644 --- a/crosschain-resolver/contracts/L1Resolver.sol +++ b/crosschain-resolver/contracts/L1Resolver.sol @@ -15,8 +15,9 @@ import "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver import {ITargetResolver} from './ITargetResolver.sol'; import {IMetadataResolver} from './IMetadataResolver.sol'; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import { IAddrSetter } from './IAddrSetter.sol'; -contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExtendedResolver, ERC165 { +contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExtendedResolver, IAddrSetter, ERC165 { using EVMFetcher for EVMFetcher.EVMFetchRequest; using BytesUtils for bytes; IEVMVerifier public immutable verifier; @@ -29,7 +30,7 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte uint256 constant VERSIONABLE_HASHES_SLOT = 3; uint256 constant VERSIONABLE_TEXTS_SLOT = 10; string public graphqlUrl; - uint256 public l2ResolverCoinType; + uint256 public l2ChainId; event TargetSet(bytes name, address target); function isAuthorised(bytes32 node) internal view returns (bool) { @@ -45,19 +46,29 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte return owner == msg.sender; } + /** + * @dev EIP-5559 - Error to raise when mutations are being deferred to an L2. + * @param chainId Chain ID to perform the deferred mutation to. + * @param contractAddress Contract Address at which the deferred mutation should transact with. + */ + error StorageHandledByL2( + uint256 chainId, + address contractAddress + ); + /** * @param _verifier The chain verifier address * @param _ens The ENS registry address * @param _nameWrapper The ENS name wrapper address * @param _graphqlUrl The offchain/l2 graphql endpoint url - * @param _l2ResolverCoinType The chainId at which the resolver resolves data from. 0 if storageLocation is offChain + * @param _l2ChainId The chainId at which the resolver resolves data from */ constructor( IEVMVerifier _verifier, ENS _ens, INameWrapper _nameWrapper, string memory _graphqlUrl, - uint256 _l2ResolverCoinType + uint256 _l2ChainId ){ require(address(_nameWrapper) != address(0), "Name Wrapper address must be set"); require(address(_verifier) != address(0), "Verifier address must be set"); @@ -66,7 +77,7 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte ens = _ens; nameWrapper = _nameWrapper; graphqlUrl = _graphqlUrl; - l2ResolverCoinType = _l2ResolverCoinType; + l2ChainId = _l2ChainId; } /** @@ -79,19 +90,9 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte require(isAuthorised(node)); targets[node] = target; emit TargetSet(name, target); - ( - ,, - uint8 storageType, - bytes memory storageLocation, - bytes memory context - ) = metadata(name); emit MetadataChanged( name, - l2ResolverCoinType, - graphqlUrl, - storageType, - storageLocation, - context + graphqlUrl ); } @@ -163,6 +164,17 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte } } + /** + * @dev Resolve and throws an EIP 3559 compliant error + * @param name DNS encoded ENS name to query + * @param _addr The actual calldata + * @return result result of the call + */ + function setAddr(bytes calldata name, address _addr) external view returns (bytes memory result) { + (, address target) = _getTarget(name, 0); + _writeDeferral(target); + } + function _addr(bytes32 node, address target) private view returns (bytes memory) { EVMFetcher.newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) @@ -246,23 +258,13 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte * @notice Get metadata about the L1 Resolver * @dev This function provides metadata about the L1 Resolver, including its name, coin type, GraphQL URL, storage type, and encoded information. * @param name The domain name in format (dnsEncoded) - * @return coinType The cointype of the chain the target contract locates such as Optimism, Base, Arb, etc * @return graphqlUrl The GraphQL URL used by the resolver - * @return storageType Storage Type (0 for EVM) - * @return storageLocation The storage identifier. For EVM chains, this is the address of the resolver contract. - * @return context. An identifier used by l2 graph indexer for Domain schema id (`context-namehash`) allowing multiple resolver contracts to have own namespace. */ function metadata( bytes calldata name - ) public view returns (uint256, string memory, uint8, bytes memory, bytes memory) { - (, address target) = getTarget(name); - + ) public view returns (string memory) { return ( - l2ResolverCoinType, - graphqlUrl, - uint8(0), // storage Type 0 => EVM - abi.encodePacked(address(target)), // storage location => l2 resolver address - abi.encodePacked(address(target)) // context => l2 resolver address + graphqlUrl ); } @@ -273,6 +275,14 @@ contract L1Resolver is EVMFetchTarget, ITargetResolver, IMetadataResolver, IExte interfaceId == type(IExtendedResolver).interfaceId || interfaceId == type(ITargetResolver).interfaceId || interfaceId == type(IMetadataResolver).interfaceId || + interfaceId == type(IAddrSetter).interfaceId || super.supportsInterface(interfaceId); } + + function _writeDeferral(address target) internal view { + revert StorageHandledByL2( + l2ChainId, + target + ); + } } diff --git a/crosschain-resolver/contracts/deps.sol b/crosschain-resolver/contracts/deps.sol index 9a885618..706dcf3d 100644 --- a/crosschain-resolver/contracts/deps.sol +++ b/crosschain-resolver/contracts/deps.sol @@ -7,7 +7,7 @@ import {ReverseRegistrar} from "@ensdomains/ens-contracts/contracts/reverseRegis import {PublicResolver} from "@ensdomains/ens-contracts/contracts/resolvers/PublicResolver.sol"; import {DelegatableResolverFactory} from "@ensdomains/ens-contracts/contracts/resolvers/DelegatableResolverFactory.sol"; import {DelegatableResolver} from "@ensdomains/ens-contracts/contracts/resolvers/DelegatableResolver.sol"; -import {L2ReverseRegistrar} from '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol'; +import {L2ReverseResolver} from '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseResolver.sol'; // Storage slot // ┌────────────────────────────┬──────────────────────────────┬──────────────┬ // │ contract │ state_variable │ storage_slot │ diff --git a/crosschain-resolver/deploy_l1/10_l1resolver.ts b/crosschain-resolver/deploy_l1/10_l1resolver.ts index 84398ae0..584f0c15 100644 --- a/crosschain-resolver/deploy_l1/10_l1resolver.ts +++ b/crosschain-resolver/deploy_l1/10_l1resolver.ts @@ -22,12 +22,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const CHAIN_NAME = process.env.CHAIN_NAME if(!['Op', 'Base', 'Arb'].includes(CHAIN_NAME)) throw ('Set $CHAIN_NAME to Op, Base, or Arb') - const L2_COINTYPE = convertEVMChainIdToCoinType(parseInt(L2_CHAIN_ID)) - console.log({VERIFIER_ADDRESS,ENS_ADDRESS, WRAPPER_ADDRESS,L2_GRAPHQL_URL,L2_COINTYPE}) + console.log({VERIFIER_ADDRESS,ENS_ADDRESS, WRAPPER_ADDRESS,L2_GRAPHQL_URL,L2_CHAIN_ID}) await deploy(`${CHAIN_NAME}L1Resolver`, { from: deployer, contract: 'L1Resolver', - args: [VERIFIER_ADDRESS,ENS_ADDRESS,WRAPPER_ADDRESS,L2_GRAPHQL_URL,L2_COINTYPE], + args: [VERIFIER_ADDRESS,ENS_ADDRESS,WRAPPER_ADDRESS,L2_GRAPHQL_URL,parseInt(L2_CHAIN_ID)], log: true, }); }; diff --git a/crosschain-resolver/test/testResolver.ts b/crosschain-resolver/test/testResolver.ts index 5539c852..46428f74 100644 --- a/crosschain-resolver/test/testResolver.ts +++ b/crosschain-resolver/test/testResolver.ts @@ -15,12 +15,12 @@ import { ethers } from 'hardhat'; import { EthereumProvider } from 'hardhat/types'; import request from 'supertest'; import packet from 'dns-packet'; -import {convertEVMChainIdToCoinType} from '@ensdomains/address-encoder' +import { L2ChainID } from '@eth-optimism/sdk'; const labelhash = (label) => ethers.keccak256(ethers.toUtf8Bytes(label)) const encodeName = (name) => '0x' + packet.name.encode(name).toString('hex') const l2graphqlUrl = 'http://graphql' -const l2ResolverCoinType = convertEVMChainIdToCoinType(420) // Optimism Goerli +const chainId = L2ChainID.OPTIMISM_SEPOLIA const name = 'foo.eth' const node = ethers.namehash(name) @@ -30,6 +30,12 @@ const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000' const EMPTY_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000' +// looks like there are time dependencies for verification to success, hence adding a dalay +const wait = async x => { + return new Promise(resolve => { + setTimeout(resolve, 3000, 2 * x); + }); +}; type ethersObj = typeof ethersT & Omit & { @@ -148,7 +154,7 @@ describe('Crosschain Resolver', () => { signer ); const verifierAddress = await verifier.getAddress() - target = await testL1Factory.deploy(verifierAddress, ensAddress, wrapperAddress, l2graphqlUrl, l2ResolverCoinType); + target = await testL1Factory.deploy(verifierAddress, ensAddress, wrapperAddress, l2graphqlUrl, chainId); // Mine an empty block so we have something to prove against await provider.send('evm_mine', []); @@ -217,7 +223,7 @@ describe('Crosschain Resolver', () => { const result = await l2contract['addr(bytes32)'](node) expect(ethers.getAddress(result)).to.equal(addr); await provider.send("evm_mine", []); - + await wait(1); const i = new ethers.Interface(["function addr(bytes32) returns(address)"]) const calldata = i.encodeFunctionData("addr", [node]) const result2 = await target.resolve(encodedname, calldata, { enableCcipRead: true }) @@ -233,9 +239,9 @@ describe('Crosschain Resolver', () => { const result = await l2contract['addr(bytes32)'](node) expect(ethers.getAddress(result)).to.equal(addr); await provider.send("evm_mine", []); - const i = new ethers.Interface(["function addr(bytes32) returns(address)"]) const calldata = i.encodeFunctionData("addr", [node]) + await wait(1); const result2 = await target.resolve(encodedname, calldata, { enableCcipRead: true }) const decoded = i.decodeFunctionResult("addr", result2) expect(decoded[0]).to.equal(addr); @@ -252,6 +258,7 @@ describe('Crosschain Resolver', () => { const result = await l2contract['addr(bytes32)'](subnode) expect(ethers.getAddress(result)).to.equal(addr); await provider.send("evm_mine", []); + await wait(1); const i = new ethers.Interface(["function addr(bytes32) returns(address)"]) const calldata = i.encodeFunctionData("addr", [subnode]) @@ -261,13 +268,14 @@ describe('Crosschain Resolver', () => { }) it("should resolve non ETH Address", async() => { + await target.setTarget(encodedname, resolverAddress) const addr = '0x76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac' const coinType = 0 // BTC await l2contract.clearRecords(node) await l2contract['setAddr(bytes32,uint256,bytes)'](node, coinType, addr) await provider.send("evm_mine", []); - + await wait(1); const i = new ethers.Interface(["function addr(bytes32,uint256) returns(bytes)"]) const calldata = i.encodeFunctionData("addr", [node, coinType]) const result2 = await target.resolve(encodedname, calldata, { enableCcipRead: true }) @@ -282,7 +290,7 @@ describe('Crosschain Resolver', () => { await l2contract.clearRecords(node) await l2contract.setText(node, key, value) await provider.send("evm_mine", []); - + await wait(1); const i = new ethers.Interface(["function text(bytes32,string) returns(string)"]) const calldata = i.encodeFunctionData("text", [node, key]) const result2 = await target.resolve(encodedname, calldata, { enableCcipRead: true }) @@ -296,7 +304,7 @@ describe('Crosschain Resolver', () => { await l2contract.clearRecords(node) await l2contract.setContenthash(node, contenthash) await provider.send("evm_mine", []); - + await wait(1); const i = new ethers.Interface(["function contenthash(bytes32) returns(bytes)"]) const calldata = i.encodeFunctionData("contenthash", [node]) const result2 = await target.resolve(encodedname, calldata, { enableCcipRead: true }) @@ -309,31 +317,30 @@ describe('Crosschain Resolver', () => { expect(await target.supportsInterface('0x9061b923')).to.equal(true) // IExtendedResolver expect(await target.supportsInterface('0x8a596ebe')).to.equal(true) // IMetadataResolver expect(await target.supportsInterface('0x01ffc9a7')).to.equal(true) // ERC-165 support + expect(await target.supportsInterface('0xf00eebf4')).to.equal(true) // IAddrSetter support }) + describe('EIP 5559', () => { + it('throws StorageHandledByL2 error', async () => { + await target.setTarget(encodedname, resolverAddress) + await expect(target.setAddr(encodedname, EMPTY_ADDRESS)).to.be + .revertedWithCustomError(target, 'StorageHandledByL2') + .withArgs(chainId, resolverAddress) + }); + }); + describe('Metadata', () => { it('returns metadata', async () => { - await target.setTarget(encodedname, signerAddress) - - const [coinType, graphqlUrl, storageType, storageLocation, context] = await target.metadata(encodedname); - expect(parseInt(coinType)).to.equal(l2ResolverCoinType); - expect(graphqlUrl).to.equal(l2graphqlUrl); - expect(storageType).to.equal(storageType); - expect(ethers.getAddress(storageLocation)).to.equal(signerAddress); - expect(ethers.getAddress(context)).to.equal(signerAddress); + expect(await target.metadata(encodedname)).to.equal(l2graphqlUrl); }); it('emits a MetadataChanged event', async () => { const tx = await target.setTarget(encodedname, signerAddress) await tx.wait() const logs = await target.queryFilter("MetadataChanged") - const [name, coinType, graphqlUrl, storageType, storageLocation, context] = logs[0].args + const [name, graphqlUrl] = logs[0].args expect(name).to.equal(encodedname); - expect(parseInt(coinType)).to.equal(l2ResolverCoinType); expect(graphqlUrl).to.equal(l2graphqlUrl); - expect(storageType).to.equal(storageType); - expect(ethers.getAddress(storageLocation)).to.equal(signerAddress); - expect(ethers.getAddress(context)).to.equal(signerAddress); }); }); }); \ No newline at end of file diff --git a/crosschain-reverse-resolver/README.md b/crosschain-reverse-resolver/README.md index 0b4f7829..a37cbbfe 100644 --- a/crosschain-reverse-resolver/README.md +++ b/crosschain-reverse-resolver/README.md @@ -36,30 +36,77 @@ After deployment is complete, set the rersolver of $REVERSE_NAMESPACE to L1Rever ## Deployments +### L1 + +- DefaultReverseResolver = [0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0](https://sepolia.etherscan.io/address/0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0#code +) + ### OP #### L2 -- L2ReverseRegistrar = [0xfdF30e5E06d728704A42bac6E0326538E659a67B](https://sepolia-optimism.etherscan.io/address/0xfdF30e5E06d728704A42bac6E0326538E659a67B#code +- L2ReverseRegistrar = [0x83C058D2139a6eFA32E42BeB415409000C075563](https://sepolia-optimism.etherscan.io/address/0x83C058D2139a6eFA32E42BeB415409000C075563#code ) = REVERSE_NAMESPACE is set to `2158639068.reverse` #### L1 -- L1ReverseResolver = [0xCCe95773C00b924c9EB60822c970eBA2884Ef6A3](https://sepolia.etherscan.io/address/0xCCe95773C00b924c9EB60822c970eBA2884Ef6A3#code) +- L1ReverseResolver = [0xF7e3a2861FfA833C39544B7bbE9D94f3219E5b70](https://sepolia.etherscan.io/address/0xF7e3a2861FfA833C39544B7bbE9D94f3219E5b70#code) ### Base #### L2 -- L2ReverseRegistrar = [0xF2c102E96A183fC598d83fDccF4e30cfE83aedCd](https://sepolia.basescan.org/address/0xF2c102E96A183fC598d83fDccF4e30cfE83aedCd#code) = REVERSE_NAMESPACE is set to `2147568180.reverse` +- L2ReverseRegistrar = [0x913CC39C2A6aa4A1531429C079bA5f8DcF6a2FC2](https://sepolia.basescan.org/address/0x913CC39C2A6aa4A1531429C079bA5f8DcF6a2FC2#code) = REVERSE_NAMESPACE is set to `2147568180.reverse` #### L1 -- L1ReverseResolver = [0x2B07Cf3ef421A5ff1cb6f437036bdEF132eEA37B](https://sepolia.etherscan.io/address/0x2B07Cf3ef421A5ff1cb6f437036bdEF132eEA37B#code) +- L1ReverseResolver = [0x302096e94FC120A21053f7563e2Ed554d523ba41](https://sepolia.etherscan.io/address/0x302096e94FC120A21053f7563e2Ed554d523ba41#code +) ### Arbitrum #### L2 -- L2ReverseRegistrar = [0xeC6D530EDc9c783F58Da1aD41C3c5B63C3095720](https://sepolia.arbiscan.io/address/0xeC6D530EDc9c783F58Da1aD41C3c5B63C3095720#code +- L2ReverseRegistrar = [0x60a384Cfbb088Aa8c1750A04548b1b983CDc0418](https://sepolia.arbiscan.io/address/0x60a384Cfbb088Aa8c1750A04548b1b983CDc0418#code ) = REVERSE_NAMESPACE is set to `2147905262.reverse` #### L1 -- L1ReverseResolver = [0x065cB486e830bc5517D2a4287e0857cd564a476D](https://sepolia.etherscan.io/address/0x065cB486e830bc5517D2a4287e0857cd564a476D#code) +- L1ReverseResolver = [0x935510B4270F69c6fa4Fadab75B4EA0A1Fb68349]https://sepolia.etherscan.io/address/0x935510B4270F69c6fa4Fadab75B4EA0A1Fb68349#code) + ## Usage +### Set Default Primary name on L1 + +``` +const testSigner = new ethers.Wallet(PRIVATE_KEY); +const testAddress = testSigner.address +const name = 'myname.eth' +const reverseLabel = testAddress.substring(2).toLowerCase() +const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` +const l2ReverseNode = ethers.namehash(l2ReverseName) +const encodedL2ReverseName = encodeName(l2ReverseName) + +const defaultReverseName = `${reverseLabel}.default.reverse` +const defaultReverseNode = ethers.namehash(defaultReverseName) +const encodedDefaultReverseName = encodeName(defaultReverseName) + +const funcId = ethers + .id('setNameForAddrWithSignature(address,string,uint256,bytes)') + .substring(0, 10) + +const block = await provider.getBlock('latest') +const inceptionDate = block?.timestamp +const message = ethers.solidityPackedKeccak256( + ['bytes32', 'address', 'uint256', 'uint256'], + [ethers.solidityPackedKeccak256(['bytes4', 'string'], [funcId, name]), testAddress, inceptionDate, 0], +) +const signature = await testSigner.signMessage(ethers.toBeArray(message)) +await defaultReverseResolver.setNameForAddrWithSignature( + testAddress, + name, + inceptionDate, + signature, +) +``` + +or run the script +``` +DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY REVERSE_NAMESPACE=$REVERSE_NAMESPACE L1_PROVIDER_URL=$L1_PROVIDER_URL DEFAULT_REVERSE_RESOLVER_ADDRESS=$DEFAULT_REVERSE_RESOLVER_ADDRESS DEFAULT_ENS_NAME=$DEFAULT_ENS_NAME yarn setdefaultname +``` + + ### Set Primary name on L2 ``` diff --git a/crosschain-reverse-resolver/contracts/DefaultReverseResolver.sol b/crosschain-reverse-resolver/contracts/DefaultReverseResolver.sol new file mode 100644 index 00000000..5f74d862 --- /dev/null +++ b/crosschain-reverse-resolver/contracts/DefaultReverseResolver.sol @@ -0,0 +1,97 @@ +pragma solidity >=0.8.4; + +import "./IDefaultReverseResolver.sol"; +import "@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol"; +import "@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {ITextResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol"; +import {INameResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol"; +import "@ensdomains/ens-contracts/contracts/utils/HexUtils.sol"; +import "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol"; + +/** + * A fallback reverser resolver to resolve when L2 reverse resolver has no names set. + * The contract will be set under "default.reverse" namespace + * It can only be set by EOA as contract accounts are chain dependent. + */ +contract DefaultReverseResolver is + Ownable, + IDefaultReverseResolver, + IExtendedResolver, + ERC165, + SignatureReverseResolver +{ + uint256 constant ADDRESS_LENGTH = 40; + using ECDSA for bytes32; + using BytesUtils for bytes; + // The namehash of 'default.reverse' + bytes32 private constant DEFAULT_REVERSE_NODE = + 0x53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd312; + + /** + * @dev Constructor + */ + constructor() SignatureReverseResolver(DEFAULT_REVERSE_NODE, 0) {} + + function isAuthorised(address addr) internal view override returns (bool) { + if (addr != msg.sender) { + revert Unauthorised(); + } + } + + /* + * Returns the name associated with an address, for reverse records. + * This function is non ENSIP standard + * @param address The ENS address to query. + * @return The associated name. + */ + function name(address addr) public view returns (string memory) { + bytes32 node = _getNamehash(addr); + return versionable_names[recordVersions[node]][node]; + } + + /* + * Returns the text data associated with an address and key. + * @param address The ENS address to query. + * @param key The text data key to query. + * @return The associated text data. + */ + function text( + address addr, + string memory key + ) public view override returns (string memory) { + bytes32 node = _getNamehash(addr); + return versionable_texts[recordVersions[node]][node][key]; + } + + /* + * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver + * @param name DNS encoded ENS name to query + * @param data The actual calldata + * @return result result of the call + */ + function resolve(bytes calldata _name, bytes calldata data) external view returns (bytes memory result) { + bytes4 selector = bytes4(data); + (address addr,bool valid) = HexUtils.hexToAddress(_name, 1, ADDRESS_LENGTH + 1); + require(valid, "Invalid address"); + + if (selector == INameResolver.name.selector) { + return bytes(name(addr)); + } + if (selector == ITextResolver.text.selector) { + (,string memory key) = abi.decode(data[4:], (bytes32, string)); + return bytes(text(addr, key)); + } + } + + function supportsInterface( + bytes4 interfaceID + ) public view override(ERC165, SignatureReverseResolver) returns (bool) { + return + interfaceID == type(IDefaultReverseResolver).interfaceId || + interfaceID == type(IExtendedResolver).interfaceId || + super.supportsInterface(interfaceID); + } +} diff --git a/crosschain-reverse-resolver/contracts/IDefaultReverseResolver.sol b/crosschain-reverse-resolver/contracts/IDefaultReverseResolver.sol new file mode 100644 index 00000000..a0b87cf1 --- /dev/null +++ b/crosschain-reverse-resolver/contracts/IDefaultReverseResolver.sol @@ -0,0 +1,10 @@ +pragma solidity >=0.8.4; + +interface IDefaultReverseResolver { + function name(address addr) external view returns (string memory); + + function text( + address addr, + string memory key + ) external view returns (string memory); +} diff --git a/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol b/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol index 36a14e4e..92bce82f 100644 --- a/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol +++ b/crosschain-reverse-resolver/contracts/L1ReverseResolver.sol @@ -7,53 +7,73 @@ import {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol' import "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol"; import "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import "@ensdomains/ens-contracts/contracts/utils/HexUtils.sol"; +import "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol"; +import "./IDefaultReverseResolver.sol"; -contract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC165 { +contract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 { using EVMFetcher for EVMFetcher.EVMFetchRequest; IEVMVerifier immutable verifier; address immutable target; - uint256 constant VERSIONABLE_TEXTS_SLOT = 2; - uint256 constant VERSIONABLE_NAME_SLOT = 3; - uint256 constant RECORD_VERSIONS_SLOT = 4; - - constructor(IEVMVerifier _verifier, address _target) { + IDefaultReverseResolver immutable defaultReverseResolver; + uint256 constant VERSIONABLE_TEXTS_SLOT = 1; + uint256 constant VERSIONABLE_NAME_SLOT = 2; + uint256 constant RECORD_VERSIONS_SLOT = 3; + uint256 constant ADDRESS_LENGTH = 40; + using HexUtils for bytes; + + constructor(IEVMVerifier _verifier, address _target, IDefaultReverseResolver _defaultReverseResolver ) { verifier = _verifier; target = _target; + defaultReverseResolver = _defaultReverseResolver; } - /** - * Returns the address associated with an ENS node. - * @param node The ENS node to query. - * @return The associated name. + /** + * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver + * @param name DNS encoded ENS name to query + * @param data The actual calldata + * @return result result of the call */ - // return versionable_names[recordVersions[node]][node]; - function name(bytes32 node) public view returns (string memory) { + function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) { + bytes4 selector = bytes4(data); + (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1); + if (selector == INameResolver.name.selector) { + (bytes32 node) = abi.decode(data[4:], (bytes32)); + return bytes(_name(node, addr)); + } + if (selector == ITextResolver.text.selector) { + (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string)); + return bytes(_text(node, key, addr)); + } + } + + function _name(bytes32 node, address addr) private view returns (string memory) { EVMFetcher.newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) .element(node) .getDynamic(VERSIONABLE_NAME_SLOT) .ref(0) .element(node) - .fetch(this.nameCallback.selector, ''); // recordVersions + .fetch(this.nameCallback.selector, abi.encode(addr)); } function nameCallback( bytes[] memory values, - bytes memory - ) public pure returns (string memory) { - return string(values[1]); + bytes memory callbackdata + ) public view returns (string memory) { + if (values[1].length == 0 ) { + (address addr) = abi.decode(callbackdata, (address)); + return defaultReverseResolver.name(addr); + } else { + return string(values[1]); + } } - /** - * Returns the text data associated with an ENS node and key. - * @param node The ENS node to query. - * @param key The text data key to query. - * @return The associated text data. - */ - function text( + function _text( bytes32 node, - string calldata key - ) public view returns (string memory) { + string memory key, + address addr + ) private view returns (string memory) { EVMFetcher.newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) .element(node) @@ -61,22 +81,26 @@ contract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC1 .ref(0) .element(node) .element(key) - .fetch(this.textCallback.selector, ''); + .fetch(this.textCallback.selector, abi.encode(addr, key)); } function textCallback( bytes[] memory values, - bytes memory - ) public pure returns (string memory) { - return string(values[1]); + bytes memory callbackdata + ) public view returns (string memory) { + if (values[1].length == 0 ) { + (address addr, string memory key) = abi.decode(callbackdata, (address, string)); + return defaultReverseResolver.text(addr, key); + } else { + return string(values[1]); + } } function supportsInterface( bytes4 interfaceId ) public override view returns (bool) { return - interfaceId == type(ITextResolver).interfaceId || - interfaceId == type(INameResolver).interfaceId || + interfaceId == type(IExtendedResolver).interfaceId || super.supportsInterface(interfaceId); } } diff --git a/crosschain-reverse-resolver/contracts/deps.sol b/crosschain-reverse-resolver/contracts/deps.sol index 57d018ab..3e5c7834 100644 --- a/crosschain-reverse-resolver/contracts/deps.sol +++ b/crosschain-reverse-resolver/contracts/deps.sol @@ -1,12 +1,11 @@ import {L1Verifier} from '@ensdomains/l1-verifier/contracts/L1Verifier.sol'; -import '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol'; +import '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseResolver.sol'; import '@ensdomains/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol'; // Storage slot // ┌────────────────────┬───────────────────┬──────────────┬ // │ contract │ state_variable │ storage_slot │ // ├────────────────────┼───────────────────┼──────────────┼ -// │ L2ReverseRegistrar │ _owner │ 0 │ -// │ L2ReverseRegistrar │ lastUpdated │ 1 │ -// │ L2ReverseRegistrar │ versionable_texts │ 2 │ -// │ L2ReverseRegistrar │ versionable_names │ 3 │ -// │ L2ReverseRegistrar │ recordVersions │ 4 │ +// │ L2ReverseResolver │ lastUpdated │ 0 │ +// │ L2ReverseResolver │ versionable_texts │ 1 │ +// │ L2ReverseResolver │ versionable_names │ 2 │ +// │ L2ReverseResolver │ recordVersions │ 3 │ diff --git a/crosschain-reverse-resolver/deploy_l1/01_defaultReverseResolver.ts b/crosschain-reverse-resolver/deploy_l1/01_defaultReverseResolver.ts new file mode 100644 index 00000000..3d1e6251 --- /dev/null +++ b/crosschain-reverse-resolver/deploy_l1/01_defaultReverseResolver.ts @@ -0,0 +1,16 @@ +import {HardhatRuntimeEnvironment} from 'hardhat/types'; +import {DeployFunction} from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const {deployments, getNamedAccounts} = hre; + const {deploy} = deployments; + + const {deployer} = await getNamedAccounts(); + + await deploy(`DefaultReverseResolver`, { + from: deployer, + log: true, + }); +}; +export default func; +func.tags = ['DefaultReverseResolver']; diff --git a/crosschain-reverse-resolver/deploy_l1/10_l1resolver.ts b/crosschain-reverse-resolver/deploy_l1/10_l1resolver.ts index 2c819c0d..6987c026 100644 --- a/crosschain-reverse-resolver/deploy_l1/10_l1resolver.ts +++ b/crosschain-reverse-resolver/deploy_l1/10_l1resolver.ts @@ -4,6 +4,8 @@ import {DeployFunction} from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {deployments, getNamedAccounts} = hre; + const DefaultReverseResolver = await deployments.get('DefaultReverseResolver'); + const DEFAULT_REVERSE_RESOLVER_ADDRESS = DefaultReverseResolver.address const {deploy} = deployments; const {deployer} = await getNamedAccounts(); @@ -14,13 +16,16 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { if(!VERIFIER_ADDRESS) throw ('Set $VERIFIER_ADDRESS') if(!['Op', 'Base', 'Arb'].includes(CHAIN_NAME)) throw ('Set $CHAIN_NAME to Op, Base, or Arb') if(!L2_REVERSE_REGISTRAR_ADDRESS) throw ('Set $L2_REVERSE_REGISTRAR_ADDRESS') - console.log({VERIFIER_ADDRESS, L2_REVERSE_REGISTRAR_ADDRESS}) + console.log({VERIFIER_ADDRESS, L2_REVERSE_REGISTRAR_ADDRESS, DEFAULT_REVERSE_RESOLVER_ADDRESS}) await deploy(`${CHAIN_NAME}L1ReverseResolver`, { from: deployer, contract:'L1ReverseResolver', - args: [VERIFIER_ADDRESS, L2_REVERSE_REGISTRAR_ADDRESS], + args: [VERIFIER_ADDRESS, L2_REVERSE_REGISTRAR_ADDRESS, DEFAULT_REVERSE_RESOLVER_ADDRESS], log: true, }); }; export default func; +func.dependencies = [ + 'DefaultReverseResolver', +] func.tags = ['L1ReverseResolver']; diff --git a/crosschain-reverse-resolver/deployments/sepolia/ArbL1ReverseResolver.json b/crosschain-reverse-resolver/deployments/sepolia/ArbL1ReverseResolver.json index 388eaaea..e86dddb8 100644 --- a/crosschain-reverse-resolver/deployments/sepolia/ArbL1ReverseResolver.json +++ b/crosschain-reverse-resolver/deployments/sepolia/ArbL1ReverseResolver.json @@ -1,5 +1,5 @@ { - "address": "0x065cB486e830bc5517D2a4287e0857cd564a476D", + "address": "0x935510B4270F69c6fa4Fadab75B4EA0A1Fb68349", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "address", "name": "_target", "type": "address" + }, + { + "internalType": "contract IDefaultReverseResolver", + "name": "_defaultReverseResolver", + "type": "address" } ], "stateMutability": "nonpayable", @@ -96,56 +101,6 @@ "name": "TooManyCommands", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "NameChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "string", - "name": "indexedKey", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - } - ], - "name": "TextChanged", - "type": "event" - }, { "inputs": [ { @@ -167,12 +122,17 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "callbackdata", + "type": "bytes" } ], - "name": "name", + "name": "nameCallback", "outputs": [ { "internalType": "string", @@ -186,25 +146,25 @@ { "inputs": [ { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" + "internalType": "bytes", + "name": "name", + "type": "bytes" }, { "internalType": "bytes", - "name": "", + "name": "data", "type": "bytes" } ], - "name": "nameCallback", + "name": "resolve", "outputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "bytes", + "name": "result", + "type": "bytes" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -226,30 +186,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "name": "text", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -259,7 +195,7 @@ }, { "internalType": "bytes", - "name": "", + "name": "callbackdata", "type": "bytes" } ], @@ -271,74 +207,61 @@ "type": "string" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" } ], - "transactionHash": "0xd1e1c175139a64dc131b163add640ca88f31232df48bc3754ee279eae13161c8", + "transactionHash": "0x98ad47ab2d0141a8c5ee84968e95d839bd93363b154a89d267468833de89eaa1", "receipt": { "to": null, "from": "0xDBBC2C0fe2a1D0fB4056B35a22e543bEb715E7FC", - "contractAddress": "0x065cB486e830bc5517D2a4287e0857cd564a476D", - "transactionIndex": 88, - "gasUsed": "2087308", + "contractAddress": "0x935510B4270F69c6fa4Fadab75B4EA0A1Fb68349", + "transactionIndex": 60, + "gasUsed": "2427871", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xecbd918988d90678a8a72a6585f9855790178700dfec64f20176c98d8e558786", - "transactionHash": "0xd1e1c175139a64dc131b163add640ca88f31232df48bc3754ee279eae13161c8", + "blockHash": "0x5b1583bb0c0f185a6bb72d95187720ed05dbb20bcc72b595eeb2d22d83339dc1", + "transactionHash": "0x98ad47ab2d0141a8c5ee84968e95d839bd93363b154a89d267468833de89eaa1", "logs": [], - "blockNumber": 5132890, - "cumulativeGasUsed": "16279721", + "blockNumber": 5349522, + "cumulativeGasUsed": "8342287", "status": 1, "byzantium": true }, "args": [ "0x6820E47CED34D6F275c6d26C3876D48B2c1fdf27", - "0xeC6D530EDc9c783F58Da1aD41C3c5B63C3095720" + "0x60a384Cfbb088Aa8c1750A04548b1b983CDc0418", + "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0" ], - "numDeployments": 3, - "solcInputHash": "82230a92851c1800498f571d3f1bd7cb", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"name(bytes32)\":{\"notice\":\"Returns the address associated with an ENS node.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n \\n constructor(IEVMVerifier _verifier, address _target) {\\n verifier = _verifier;\\n target = _target;\\n }\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n // return versionable_names[recordVersions[node]][node];\\n function name(bytes32 node) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, ''); // recordVersions\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\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 ) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, '');\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(ITextResolver).interfaceId ||\\n interfaceId == type(INameResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0x99abd98e4a517ecbfc9f14f970dbeec2417de4184c0996163831c2e9faf25a9d\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200269a3803806200269a833981810160405281019062000037919062000156565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505050506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000d982620000ac565b9050919050565b6000620000ed82620000cc565b9050919050565b620000ff81620000e0565b81146200010b57600080fd5b50565b6000815190506200011f81620000f4565b92915050565b6200013081620000cc565b81146200013c57600080fd5b50565b600081519050620001508162000125565b92915050565b6000806040838503121562000170576200016f620000a7565b5b600062000180858286016200010e565b925050602062000193858286016200013f565b9150509250929050565b60805160a0516124c9620001d16000396000818161031d01526105b40152600081816102fc015261059301526124c96000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", + "numDeployments": 4, + "solcInputHash": "7cc7da1092d13c01f4d5f27229751af2", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"contract IDefaultReverseResolver\",\"name\":\"_defaultReverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"resolve(bytes,bytes)\":{\"details\":\"Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\",\"params\":{\"data\":\"The actual calldata\",\"name\":\"DNS encoded ENS name to query\"},\"returns\":{\"result\":\"result of the call\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/ens-contracts/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 r, bool valid) {\\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 r := or(shl(8, r), 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\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/IDefaultReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IDefaultReverseResolver {\\n function name(address addr) external view returns (string memory);\\n\\n function text(\\n address addr,\\n string memory key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x0233c067351640bcfff8824150323e34f06abf239def880164a10eb8846479cf\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport \\\"./IDefaultReverseResolver.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n IDefaultReverseResolver immutable defaultReverseResolver;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n uint256 constant ADDRESS_LENGTH = 40;\\n using HexUtils for bytes;\\n\\n constructor(IEVMVerifier _verifier, address _target, IDefaultReverseResolver _defaultReverseResolver ) {\\n verifier = _verifier;\\n target = _target;\\n defaultReverseResolver = _defaultReverseResolver;\\n }\\n\\n /** \\n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\\n * @param name DNS encoded ENS name to query\\n * @param data The actual calldata\\n * @return result result of the call\\n */\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) {\\n bytes4 selector = bytes4(data);\\n (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1);\\n if (selector == INameResolver.name.selector) {\\n (bytes32 node) = abi.decode(data[4:], (bytes32));\\n return bytes(_name(node, addr));\\n }\\n if (selector == ITextResolver.text.selector) {\\n (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string));\\n return bytes(_text(node, key, addr));\\n }\\n }\\n\\n function _name(bytes32 node, address addr) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, abi.encode(addr));\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) { \\n if(values[1].length == 0 ){\\n (address addr) = abi.decode(callbackdata, (address));\\n return defaultReverseResolver.name(addr);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function _text(\\n bytes32 node,\\n string memory key,\\n address addr\\n ) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, abi.encode(addr, key));\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) {\\n if(values[1].length == 0 ){\\n (address addr, string memory key) = abi.decode(callbackdata, (address, string));\\n return defaultReverseResolver.text(addr, key);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(IExtendedResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0xb09771bfaf5dd9a01da9efecfbc15abc43a85501d9264c23895bbbf6edf8637a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002d5838038062002d588339818101604052810190620000379190620001d0565b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506200022c565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200010e82620000e1565b9050919050565b6000620001228262000101565b9050919050565b620001348162000115565b81146200014057600080fd5b50565b600081519050620001548162000129565b92915050565b620001658162000101565b81146200017157600080fd5b50565b60008151905062000185816200015a565b92915050565b6000620001988262000101565b9050919050565b620001aa816200018b565b8114620001b657600080fd5b50565b600081519050620001ca816200019f565b92915050565b600080600060608486031215620001ec57620001eb620000dc565b5b6000620001fc8682870162000143565b93505060206200020f8682870162000174565b92505060406200022286828701620001b9565b9150509250925092565b60805160a05160c051612ae762000271600039600081816101f2015261063a015260008181610870015261095f01526000818161084f015261093e0152612ae76000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": { "getStorageSlotsCallback(bytes,bytes)": { "details": "Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request." }, - "name(bytes32)": { + "resolve(bytes,bytes)": { + "details": "Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver", "params": { - "node": "The ENS node to query." + "data": "The actual calldata", + "name": "DNS encoded ENS name to query" }, "returns": { - "_0": "The associated name." + "result": "result of the call" } }, "supportsInterface(bytes4)": { "details": "See {IERC165-supportsInterface}." - }, - "text(bytes32,string)": { - "params": { - "key": "The text data key to query.", - "node": "The ENS node to query." - }, - "returns": { - "_0": "The associated text data." - } } }, "version": 1 }, "userdoc": { "kind": "user", - "methods": { - "name(bytes32)": { - "notice": "Returns the address associated with an ENS node." - }, - "text(bytes32,string)": { - "notice": "Returns the text data associated with an ENS node and key." - } - }, + "methods": {}, "version": 1 }, "storageLayout": { diff --git a/crosschain-reverse-resolver/deployments/sepolia/BaseL1ReverseResolver.json b/crosschain-reverse-resolver/deployments/sepolia/BaseL1ReverseResolver.json index eb296232..efbe36c6 100644 --- a/crosschain-reverse-resolver/deployments/sepolia/BaseL1ReverseResolver.json +++ b/crosschain-reverse-resolver/deployments/sepolia/BaseL1ReverseResolver.json @@ -1,5 +1,5 @@ { - "address": "0x2B07Cf3ef421A5ff1cb6f437036bdEF132eEA37B", + "address": "0x302096e94FC120A21053f7563e2Ed554d523ba41", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "address", "name": "_target", "type": "address" + }, + { + "internalType": "contract IDefaultReverseResolver", + "name": "_defaultReverseResolver", + "type": "address" } ], "stateMutability": "nonpayable", @@ -96,56 +101,6 @@ "name": "TooManyCommands", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "NameChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "string", - "name": "indexedKey", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - } - ], - "name": "TextChanged", - "type": "event" - }, { "inputs": [ { @@ -167,12 +122,17 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "callbackdata", + "type": "bytes" } ], - "name": "name", + "name": "nameCallback", "outputs": [ { "internalType": "string", @@ -186,25 +146,25 @@ { "inputs": [ { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" + "internalType": "bytes", + "name": "name", + "type": "bytes" }, { "internalType": "bytes", - "name": "", + "name": "data", "type": "bytes" } ], - "name": "nameCallback", + "name": "resolve", "outputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "bytes", + "name": "result", + "type": "bytes" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -226,30 +186,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "name": "text", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -259,7 +195,7 @@ }, { "internalType": "bytes", - "name": "", + "name": "callbackdata", "type": "bytes" } ], @@ -271,74 +207,61 @@ "type": "string" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" } ], - "transactionHash": "0x7c2ba86dc7269baf194b8ba7eebd36cde0f2d812ef13f8601d9c7fcade20bdfa", + "transactionHash": "0x60cad5b48803cc71a0588b4059d40b60bfd5a81a1fdf26a8734a05814d82d797", "receipt": { "to": null, "from": "0xDBBC2C0fe2a1D0fB4056B35a22e543bEb715E7FC", - "contractAddress": "0x2B07Cf3ef421A5ff1cb6f437036bdEF132eEA37B", - "transactionIndex": 81, - "gasUsed": "2087308", + "contractAddress": "0x302096e94FC120A21053f7563e2Ed554d523ba41", + "transactionIndex": 42, + "gasUsed": "2427871", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x71d5240937f90a68cdc54c0e576b75045b422f1b0173c2b3d289dacdd3eef3a4", - "transactionHash": "0x7c2ba86dc7269baf194b8ba7eebd36cde0f2d812ef13f8601d9c7fcade20bdfa", + "blockHash": "0x65dd1dd6b3a969bc04d15d760f862dd91779f2bf5254e517c16d33db7de6e7e8", + "transactionHash": "0x60cad5b48803cc71a0588b4059d40b60bfd5a81a1fdf26a8734a05814d82d797", "logs": [], - "blockNumber": 5132875, - "cumulativeGasUsed": "9971705", + "blockNumber": 5347538, + "cumulativeGasUsed": "8072240", "status": 1, "byzantium": true }, "args": [ "0xAdef74372444e716C0473dEe1F9Cb3108EFa3818", - "0xF2c102E96A183fC598d83fDccF4e30cfE83aedCd" + "0x913CC39C2A6aa4A1531429C079bA5f8DcF6a2FC2", + "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0" ], - "numDeployments": 2, - "solcInputHash": "82230a92851c1800498f571d3f1bd7cb", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"name(bytes32)\":{\"notice\":\"Returns the address associated with an ENS node.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n \\n constructor(IEVMVerifier _verifier, address _target) {\\n verifier = _verifier;\\n target = _target;\\n }\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n // return versionable_names[recordVersions[node]][node];\\n function name(bytes32 node) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, ''); // recordVersions\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\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 ) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, '');\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(ITextResolver).interfaceId ||\\n interfaceId == type(INameResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0x99abd98e4a517ecbfc9f14f970dbeec2417de4184c0996163831c2e9faf25a9d\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200269a3803806200269a833981810160405281019062000037919062000156565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505050506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000d982620000ac565b9050919050565b6000620000ed82620000cc565b9050919050565b620000ff81620000e0565b81146200010b57600080fd5b50565b6000815190506200011f81620000f4565b92915050565b6200013081620000cc565b81146200013c57600080fd5b50565b600081519050620001508162000125565b92915050565b6000806040838503121562000170576200016f620000a7565b5b600062000180858286016200010e565b925050602062000193858286016200013f565b9150509250929050565b60805160a0516124c9620001d16000396000818161031d01526105b40152600081816102fc015261059301526124c96000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", + "numDeployments": 4, + "solcInputHash": "7cc7da1092d13c01f4d5f27229751af2", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"contract IDefaultReverseResolver\",\"name\":\"_defaultReverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"resolve(bytes,bytes)\":{\"details\":\"Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\",\"params\":{\"data\":\"The actual calldata\",\"name\":\"DNS encoded ENS name to query\"},\"returns\":{\"result\":\"result of the call\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/ens-contracts/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 r, bool valid) {\\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 r := or(shl(8, r), 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\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/IDefaultReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IDefaultReverseResolver {\\n function name(address addr) external view returns (string memory);\\n\\n function text(\\n address addr,\\n string memory key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x0233c067351640bcfff8824150323e34f06abf239def880164a10eb8846479cf\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport \\\"./IDefaultReverseResolver.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n IDefaultReverseResolver immutable defaultReverseResolver;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n uint256 constant ADDRESS_LENGTH = 40;\\n using HexUtils for bytes;\\n\\n constructor(IEVMVerifier _verifier, address _target, IDefaultReverseResolver _defaultReverseResolver ) {\\n verifier = _verifier;\\n target = _target;\\n defaultReverseResolver = _defaultReverseResolver;\\n }\\n\\n /** \\n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\\n * @param name DNS encoded ENS name to query\\n * @param data The actual calldata\\n * @return result result of the call\\n */\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) {\\n bytes4 selector = bytes4(data);\\n (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1);\\n if (selector == INameResolver.name.selector) {\\n (bytes32 node) = abi.decode(data[4:], (bytes32));\\n return bytes(_name(node, addr));\\n }\\n if (selector == ITextResolver.text.selector) {\\n (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string));\\n return bytes(_text(node, key, addr));\\n }\\n }\\n\\n function _name(bytes32 node, address addr) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, abi.encode(addr));\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) { \\n if(values[1].length == 0 ){\\n (address addr) = abi.decode(callbackdata, (address));\\n return defaultReverseResolver.name(addr);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function _text(\\n bytes32 node,\\n string memory key,\\n address addr\\n ) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, abi.encode(addr, key));\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) {\\n if(values[1].length == 0 ){\\n (address addr, string memory key) = abi.decode(callbackdata, (address, string));\\n return defaultReverseResolver.text(addr, key);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(IExtendedResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0xb09771bfaf5dd9a01da9efecfbc15abc43a85501d9264c23895bbbf6edf8637a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002d5838038062002d588339818101604052810190620000379190620001d0565b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506200022c565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200010e82620000e1565b9050919050565b6000620001228262000101565b9050919050565b620001348162000115565b81146200014057600080fd5b50565b600081519050620001548162000129565b92915050565b620001658162000101565b81146200017157600080fd5b50565b60008151905062000185816200015a565b92915050565b6000620001988262000101565b9050919050565b620001aa816200018b565b8114620001b657600080fd5b50565b600081519050620001ca816200019f565b92915050565b600080600060608486031215620001ec57620001eb620000dc565b5b6000620001fc8682870162000143565b93505060206200020f8682870162000174565b92505060406200022286828701620001b9565b9150509250925092565b60805160a05160c051612ae762000271600039600081816101f2015261063a015260008181610870015261095f01526000818161084f015261093e0152612ae76000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": { "getStorageSlotsCallback(bytes,bytes)": { "details": "Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request." }, - "name(bytes32)": { + "resolve(bytes,bytes)": { + "details": "Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver", "params": { - "node": "The ENS node to query." + "data": "The actual calldata", + "name": "DNS encoded ENS name to query" }, "returns": { - "_0": "The associated name." + "result": "result of the call" } }, "supportsInterface(bytes4)": { "details": "See {IERC165-supportsInterface}." - }, - "text(bytes32,string)": { - "params": { - "key": "The text data key to query.", - "node": "The ENS node to query." - }, - "returns": { - "_0": "The associated text data." - } } }, "version": 1 }, "userdoc": { "kind": "user", - "methods": { - "name(bytes32)": { - "notice": "Returns the address associated with an ENS node." - }, - "text(bytes32,string)": { - "notice": "Returns the text data associated with an ENS node and key." - } - }, + "methods": {}, "version": 1 }, "storageLayout": { diff --git a/crosschain-reverse-resolver/deployments/sepolia/DefaultReverseResolver.json b/crosschain-reverse-resolver/deployments/sepolia/DefaultReverseResolver.json new file mode 100644 index 00000000..c60c0c76 --- /dev/null +++ b/crosschain-reverse-resolver/deployments/sepolia/DefaultReverseResolver.json @@ -0,0 +1,636 @@ +{ + "address": "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "SignatureOutOfDate", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "ReverseClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVersion", + "type": "uint64" + } + ], + "name": "VersionChanged", + "type": "event" + }, + { + "inputs": [], + "name": "ParentNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "inceptionDate", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "clearRecordsWithSignature", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "coinType", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "lastUpdated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "node", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "result", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "uint256", + "name": "inceptionDate", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "setNameForAddrWithSignature", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "internalType": "uint256", + "name": "inceptionDate", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "setTextForAddrWithSignature", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x2bfbc046dddcc1c7b76b87d9d5cdb94337b907303d484d7e66d0d843f6a229f6", + "receipt": { + "to": null, + "from": "0xDBBC2C0fe2a1D0fB4056B35a22e543bEb715E7FC", + "contractAddress": "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0", + "transactionIndex": 63, + "gasUsed": "2371577", + "logsBloom": "0x00000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000004000000000000000000000000030000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000020000000000000000000000000000000000000000000000000", + "blockHash": "0xebb9184c7909f018f7ac00a1ea0da22b9044e71d97b2c14939c2d83ef3fab7e1", + "transactionHash": "0x2bfbc046dddcc1c7b76b87d9d5cdb94337b907303d484d7e66d0d843f6a229f6", + "logs": [ + { + "transactionIndex": 63, + "blockNumber": 5347089, + "transactionHash": "0x2bfbc046dddcc1c7b76b87d9d5cdb94337b907303d484d7e66d0d843f6a229f6", + "address": "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000dbbc2c0fe2a1d0fb4056b35a22e543beb715e7fc" + ], + "data": "0x", + "logIndex": 60, + "blockHash": "0xebb9184c7909f018f7ac00a1ea0da22b9044e71d97b2c14939c2d83ef3fab7e1" + } + ], + "blockNumber": 5347089, + "cumulativeGasUsed": "7199924", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 2, + "solcInputHash": "776c7519acf1eee16c4cde4c93293488", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureOutOfDate\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ReverseClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVersion\",\"type\":\"uint64\"}],\"name\":\"VersionChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ParentNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inceptionDate\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"clearRecordsWithSignature\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"coinType\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"lastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"node\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"inceptionDate\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"setNameForAddrWithSignature\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"inceptionDate\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"setTextForAddrWithSignature\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"clearRecordsWithSignature(address,uint256,bytes)\":{\"params\":{\"addr\":\"The node to update.\",\"signature\":\"A signature proving ownership of the node.\"}},\"constructor\":{\"details\":\"Constructor\"},\"node(address)\":{\"details\":\"Returns the node hash for a given account's reverse records.\",\"params\":{\"addr\":\"The address to hash\"},\"returns\":{\"_0\":\"The ENS node hash.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setNameForAddrWithSignature(address,string,uint256,bytes)\":{\"details\":\"Sets the name for an addr using a signature that can be verified with ERC1271.\",\"params\":{\"addr\":\"The reverse record to set\",\"inceptionDate\":\"Date from when this signature is valid from\",\"name\":\"The name of the reverse record\",\"signature\":\"The resolver of the reverse node\"},\"returns\":{\"_0\":\"The ENS node hash of the reverse record.\"}},\"setTextForAddrWithSignature(address,string,string,uint256,bytes)\":{\"details\":\"Sets the name for an addr using a signature that can be verified with ERC1271.\",\"params\":{\"addr\":\"The reverse record to set\",\"inceptionDate\":\"Date from when this signature is valid from\",\"key\":\"The key of the text record\",\"signature\":\"The resolver of the reverse node\",\"value\":\"The value of the text record\"},\"returns\":{\"_0\":\"The ENS node hash of the reverse record.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"clearRecordsWithSignature(address,uint256,bytes)\":{\"notice\":\"Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry.\"}},\"notice\":\"A fallback reverser resolver to resolve when L2 reverse resolver has no names set. The contract will be set under \\\"default.reverse\\\" namespace It can only be set by EOA as contract accounts are chain dependent.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DefaultReverseResolver.sol\":\"DefaultReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x7cb1158c7d268b63de1468e28e2711b28d686e2628ddb22da2149cd93ddeafda\"},\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/ens-contracts/contracts/reverseRegistrar/ISignatureReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface ISignatureReverseResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n event ReverseClaimed(address indexed addr, bytes32 indexed node);\\n event NameChanged(bytes32 indexed node, string name);\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n function setNameForAddrWithSignature(\\n address addr,\\n string memory name,\\n uint256 inceptionDate,\\n bytes memory signature\\n ) external returns (bytes32);\\n\\n function setTextForAddrWithSignature(\\n address addr,\\n string calldata key,\\n string calldata value,\\n uint256 inceptionDate,\\n bytes memory signature\\n ) external returns (bytes32);\\n\\n function clearRecordsWithSignature(\\n address addr,\\n uint256 inceptionDate,\\n bytes memory signature\\n ) external;\\n\\n function node(address addr) external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xb5b94ce60b22a90ba943b5c2e642c3460ade7f93a9e794e58fbf6d525cfc467d\"},\"@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./ISignatureReverseResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../root/Controllable.sol\\\";\\nimport \\\"../utils/LowLevelCallUtils.sol\\\";\\n\\nerror InvalidSignature();\\nerror SignatureOutOfDate();\\nerror Unauthorised();\\n\\ncontract SignatureReverseResolver is Ownable, ISignatureReverseResolver {\\n using ECDSA for bytes32;\\n mapping(bytes32 => uint256) public lastUpdated;\\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\\n mapping(bytes32 => uint64) internal recordVersions;\\n\\n bytes32 public immutable ParentNode;\\n uint256 public immutable coinType;\\n\\n /*\\n * @dev Constructor\\n * @param ParentNode The namespace to set.\\n * @param _coinType The cointype converted from the chainId of the chain this contract is deployed to.\\n */\\n constructor(bytes32 _ParentNode, uint256 _coinType) {\\n ParentNode = _ParentNode;\\n coinType = _coinType;\\n }\\n\\n modifier authorised(address addr) {\\n isAuthorised(addr);\\n _;\\n }\\n\\n modifier authorisedSignature(\\n bytes32 hash,\\n address addr,\\n uint256 inceptionDate,\\n bytes memory signature\\n ) {\\n isAuthorisedWithSignature(hash, addr, inceptionDate, signature);\\n _;\\n }\\n\\n function getLastUpdated(\\n bytes32 node\\n ) internal view virtual returns (uint256) {\\n return lastUpdated[node];\\n }\\n\\n function isAuthorised(address addr) internal view virtual returns (bool) {}\\n\\n function isAuthorisedWithSignature(\\n bytes32 hash,\\n address addr,\\n uint256 inceptionDate,\\n bytes memory signature\\n ) internal view returns (bool) {\\n bytes32 message = keccak256(\\n abi.encodePacked(hash, addr, inceptionDate, coinType)\\n ).toEthSignedMessageHash();\\n bytes32 node = _getNamehash(addr);\\n\\n if (!SignatureChecker.isValidSignatureNow(addr, message, signature)) {\\n revert InvalidSignature();\\n }\\n\\n if (\\n inceptionDate <= lastUpdated[node] || // must be newer than current record\\n inceptionDate / 1000 >= block.timestamp // must be in the past\\n ) {\\n revert SignatureOutOfDate();\\n }\\n }\\n\\n /**\\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\\n * @param addr The reverse record to set\\n * @param name The name of the reverse record\\n * @param inceptionDate Date from when this signature is valid from\\n * @param signature The resolver of the reverse node\\n * @return The ENS node hash of the reverse record.\\n */\\n function setNameForAddrWithSignature(\\n address addr,\\n string memory name,\\n uint256 inceptionDate,\\n bytes memory signature\\n )\\n public\\n authorisedSignature(\\n keccak256(\\n abi.encodePacked(\\n ISignatureReverseResolver\\n .setNameForAddrWithSignature\\n .selector,\\n name\\n )\\n ),\\n addr,\\n inceptionDate,\\n signature\\n )\\n returns (bytes32)\\n {\\n bytes32 node = _getNamehash(addr);\\n _setName(node, name, inceptionDate);\\n emit ReverseClaimed(addr, node);\\n return node;\\n }\\n\\n /**\\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\\n * @param addr The reverse record to set\\n * @param key The key of the text record\\n * @param value The value of the text record\\n * @param inceptionDate Date from when this signature is valid from\\n * @param signature The resolver of the reverse node\\n * @return The ENS node hash of the reverse record.\\n */\\n function setTextForAddrWithSignature(\\n address addr,\\n string calldata key,\\n string calldata value,\\n uint256 inceptionDate,\\n bytes memory signature\\n )\\n public\\n authorisedSignature(\\n keccak256(\\n abi.encodePacked(\\n ISignatureReverseResolver\\n .setTextForAddrWithSignature\\n .selector,\\n key,\\n value\\n )\\n ),\\n addr,\\n inceptionDate,\\n signature\\n )\\n returns (bytes32)\\n {\\n bytes32 node = _getNamehash(addr);\\n _setText(node, key, value, inceptionDate);\\n return node;\\n }\\n\\n function _setText(\\n bytes32 node,\\n string calldata key,\\n string calldata value,\\n uint256 inceptionDate\\n ) internal {\\n versionable_texts[recordVersions[node]][node][key] = value;\\n _setLastUpdated(node, inceptionDate);\\n emit TextChanged(node, key, key, 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 ) internal view returns (string memory) {\\n return versionable_texts[recordVersions[node]][node][key];\\n }\\n\\n function _setName(\\n bytes32 node,\\n string memory newName,\\n uint256 inceptionDate\\n ) internal virtual {\\n versionable_names[recordVersions[node]][node] = newName;\\n _setLastUpdated(node, inceptionDate);\\n emit NameChanged(node, newName);\\n }\\n\\n function _name(bytes32 node) internal view returns (string memory) {\\n return versionable_names[recordVersions[node]][node];\\n }\\n\\n /**\\n * Increments the record version associated with an ENS node.\\n * May only be called by the owner of that node in the ENS registry.\\n * @param addr The node to update.\\n */\\n function _clearRecords(address addr) internal {\\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\\n bytes32 reverseNode = keccak256(\\n abi.encodePacked(ParentNode, labelHash)\\n );\\n recordVersions[reverseNode]++;\\n emit VersionChanged(reverseNode, recordVersions[reverseNode]);\\n }\\n\\n /**\\n * Increments the record version associated with an ENS node.\\n * May only be called by the owner of that node in the ENS registry.\\n * @param addr The node to update.\\n * @param signature A signature proving ownership of the node.\\n */\\n function clearRecordsWithSignature(\\n address addr,\\n uint256 inceptionDate,\\n bytes memory signature\\n )\\n public\\n authorisedSignature(\\n keccak256(\\n abi.encodePacked(\\n ISignatureReverseResolver.clearRecordsWithSignature.selector\\n )\\n ),\\n addr,\\n inceptionDate,\\n signature\\n )\\n {\\n _clearRecords(addr);\\n }\\n\\n /**\\n * @dev Returns the node hash for a given account's reverse records.\\n * @param addr The address to hash\\n * @return The ENS node hash.\\n */\\n function node(address addr) public view returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(\\n ParentNode,\\n LowLevelCallUtils.sha3HexAddress(addr)\\n )\\n );\\n }\\n\\n function _getNamehash(address addr) internal view returns (bytes32) {\\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\\n return keccak256(abi.encodePacked(ParentNode, labelHash));\\n }\\n\\n function _setLastUpdated(bytes32 node, uint256 inceptionDate) internal {\\n lastUpdated[node] = inceptionDate;\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual returns (bool) {\\n return interfaceID == type(ISignatureReverseResolver).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0x744b95377116387834e4361b374818cf3968229237250cdb24b8da1809a74432\"},\"@ensdomains/ens-contracts/contracts/root/Controllable.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract Controllable is Ownable {\\n mapping(address => bool) public controllers;\\n\\n event ControllerChanged(address indexed controller, bool enabled);\\n\\n modifier onlyController() {\\n require(\\n controllers[msg.sender],\\n \\\"Controllable: Caller is not a controller\\\"\\n );\\n _;\\n }\\n\\n function setController(address controller, bool enabled) public onlyOwner {\\n controllers[controller] = enabled;\\n emit ControllerChanged(controller, enabled);\\n }\\n}\\n\",\"keccak256\":\"0xb19b8c0fafe9ca2b4bf8aaafee486fa31437672e1e1977bdf84bfe03464969db\"},\"@ensdomains/ens-contracts/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 r, bool valid) {\\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 r := or(shl(8, r), 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\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/utils/LowLevelCallUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.13;\\n\\nimport {Address} from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nlibrary LowLevelCallUtils {\\n // This is the hex encoding of the string 'abcdefghijklmnopqrstuvwxyz'\\n // It is used as a constant to lookup the characters of the hex address\\n bytes32 constant lookup =\\n 0x3031323334353637383961626364656600000000000000000000000000000000;\\n using Address for address;\\n\\n /**\\n * @dev Makes a static call to the specified `target` with `data`. Return data can be fetched with\\n * `returnDataSize` and `readReturnData`.\\n * @param target The address to staticcall.\\n * @param data The data to pass to the call.\\n * @return success True if the call succeeded, or false if it reverts.\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data\\n ) internal view returns (bool success) {\\n require(\\n target.isContract(),\\n \\\"LowLevelCallUtils: static call to non-contract\\\"\\n );\\n assembly {\\n success := staticcall(\\n gas(),\\n target,\\n add(data, 32),\\n mload(data),\\n 0,\\n 0\\n )\\n }\\n }\\n\\n /**\\n * @dev Returns the size of the return data of the most recent external call.\\n */\\n function returnDataSize() internal pure returns (uint256 len) {\\n assembly {\\n len := returndatasize()\\n }\\n }\\n\\n /**\\n * @dev Reads return data from the most recent external call.\\n * @param offset Offset into the return data.\\n * @param length Number of bytes to return.\\n */\\n function readReturnData(\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (bytes memory data) {\\n data = new bytes(length);\\n assembly {\\n returndatacopy(add(data, 32), offset, length)\\n }\\n }\\n\\n /**\\n * @dev Reverts with the return data from the most recent external call.\\n */\\n function propagateRevert() internal pure {\\n assembly {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n }\\n\\n /**\\n * @dev An optimised function to compute the sha3 of the lower-case\\n * hexadecimal representation of an Ethereum address.\\n * @param addr The address to hash\\n * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the\\n * input address.\\n */\\n function sha3HexAddress(address addr) internal pure returns (bytes32 ret) {\\n assembly {\\n for {\\n let i := 40\\n } gt(i, 0) {\\n\\n } {\\n i := sub(i, 1)\\n mstore8(i, byte(and(addr, 0xf), lookup))\\n addr := div(addr, 0x10)\\n i := sub(i, 1)\\n mstore8(i, byte(and(addr, 0xf), lookup))\\n addr := div(addr, 0x10)\\n }\\n\\n ret := keccak256(0, 40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc7cb7b5ffa76e35a8d7f481ba8263a2904ee638546d0334df856f4e2e43fe8b3\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nlibrary BytesUtils {\\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\",\"keccak256\":\"0xf862cd86d749158a554e3cb517efa9097331ec0cf7225117f21e96fb50c67edb\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../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 * By default, the owner account will be the one that deploys the contract. This\\n * can 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 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\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 require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\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 require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/IERC1271.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\\n\\npragma solidity ^0.8.0;\\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 *\\n * _Available since v4.1._\\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\",\"keccak256\":\"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\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\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"@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/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\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 \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\")\\n mstore(0x1c, hash)\\n message := keccak256(0x00, 0x3c)\\n }\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, \\\"\\\\x19\\\\x01\\\")\\n mstore(add(ptr, 0x02), domainSeparator)\\n mstore(add(ptr, 0x22), structHash)\\n data := keccak256(ptr, 0x42)\\n }\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\\n * `validator` and `data` according to the version 0 of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x00\\\", validator, data));\\n }\\n}\\n\",\"keccak256\":\"0x809bc3edb4bcbef8263fa616c1b60ee0004b50a8a1bfa164d8f57fd31f520c58\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\nimport \\\"../../interfaces/IERC1271.sol\\\";\\n\\n/**\\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\\n * Argent and Gnosis Safe.\\n *\\n * _Available since v4.1._\\n */\\nlibrary SignatureChecker {\\n /**\\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\\n *\\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\\n */\\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\\n return\\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\\n isValidERC1271SignatureNow(signer, hash, signature);\\n }\\n\\n /**\\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\\n * against the signer smart contract using ERC1271.\\n *\\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\\n */\\n function isValidERC1271SignatureNow(\\n address signer,\\n bytes32 hash,\\n bytes memory signature\\n ) internal view returns (bool) {\\n (bool success, bytes memory result) = signer.staticcall(\\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\\n );\\n return (success &&\\n result.length >= 32 &&\\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\\n }\\n}\\n\",\"keccak256\":\"0x3af3ca86df39aac39a0514c84459d691434a108d2151c8ce9d69f32e315cab80\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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/DefaultReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"./IDefaultReverseResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {ITextResolver} from \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport {INameResolver} from \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\n\\n/**\\n * A fallback reverser resolver to resolve when L2 reverse resolver has no names set.\\n * The contract will be set under \\\"default.reverse\\\" namespace\\n * It can only be set by EOA as contract accounts are chain dependent.\\n */\\ncontract DefaultReverseResolver is\\n Ownable,\\n IDefaultReverseResolver,\\n IExtendedResolver,\\n ERC165,\\n SignatureReverseResolver\\n{\\n uint256 constant ADDRESS_LENGTH = 40;\\n using ECDSA for bytes32;\\n using BytesUtils for bytes;\\n // The namehash of 'default.reverse'\\n bytes32 private constant DEFAULT_REVERSE_NODE =\\n 0x53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd312;\\n\\n /**\\n * @dev Constructor\\n */\\n constructor() SignatureReverseResolver(DEFAULT_REVERSE_NODE, 0) {}\\n\\n function isAuthorised(address addr) internal view override returns (bool) {\\n if (addr != msg.sender) {\\n revert Unauthorised();\\n }\\n }\\n\\n /*\\n * Returns the name associated with an address, for reverse records.\\n * This function is non ENSIP standard\\n * @param address The ENS address to query.\\n * @return The associated name.\\n */\\n function name(address addr) public view returns (string memory) {\\n bytes32 node = _getNamehash(addr);\\n return versionable_names[recordVersions[node]][node];\\n }\\n\\n /*\\n * Returns the text data associated with an address and key.\\n * @param address The ENS address to query.\\n * @param key The text data key to query.\\n * @return The associated text data.\\n */\\n function text(\\n address addr,\\n string memory key\\n ) public view returns (string memory) {\\n bytes32 node = _getNamehash(addr);\\n return versionable_texts[recordVersions[node]][node][key];\\n }\\n\\n /*\\n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\\n * @param name DNS encoded ENS name to query\\n * @param data The actual calldata\\n * @return result result of the call\\n */\\n function resolve(bytes calldata _name, bytes calldata data) external view returns (bytes memory result) {\\n bytes4 selector = bytes4(data);\\n (address addr,) = HexUtils.hexToAddress(_name, 1, ADDRESS_LENGTH + 1);\\n if (selector == INameResolver.name.selector) {\\n return bytes(name(addr));\\n }\\n if (selector == ITextResolver.text.selector) {\\n (,string memory key) = abi.decode(data[4:], (bytes32, string));\\n return bytes(text(addr, key));\\n }\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC165, SignatureReverseResolver) returns (bool) {\\n return\\n interfaceID == type(IDefaultReverseResolver).interfaceId ||\\n interfaceID == type(IExtendedResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x8d2dc615019cc6b26215f0de766c4ceb18d45a41b2daeb0bcff421bfe6197f48\"},\"contracts/IDefaultReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IDefaultReverseResolver {\\n function name(address addr) external view returns (string memory);\\n\\n function text(\\n address addr,\\n string memory key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x0233c067351640bcfff8824150323e34f06abf239def880164a10eb8846479cf\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b507f53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd31260001b6000620000586200004c6200007060201b60201c565b6200007860201b60201c565b81608081815250508060a0818152505050506200013c565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60805160a05161298b6200017e600039600081816105060152610c6e01526000818161052a0152818161079d01528181610a680152611006015261298b6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063c01f93d311610066578063c01f93d314610273578063c7ee930c146102a3578063d977f6b5146102bf578063f2fde38b146102ef576100ea565b80638da5cb5b146101f55780639061b92314610213578063bffbe61c14610243576100ea565b80631fe93ea8116100c85780631fe93ea81461017f57806324d79eab1461019d578063715018a6146101bb5780637f87032e146101c5576100ea565b806301984892146100ef57806301ffc9a71461011f578063060eb2f51461014f575b600080fd5b610109600480360381019061010491906115c8565b61030b565b6040516101169190611685565b60405180910390f35b610139600480360381019061013491906116ff565b61040a565b6040516101469190611747565b60405180910390f35b61016960048036038101906101649190611798565b6104ec565b60405161017691906117de565b60405180910390f35b610187610504565b60405161019491906117de565b60405180910390f35b6101a5610528565b6040516101b29190611808565b60405180910390f35b6101c361054c565b005b6101df60048036038101906101da9190611a25565b610560565b6040516101ec9190611808565b60405180910390f35b6101fd61060e565b60405161020a9190611ad3565b60405180910390f35b61022d60048036038101906102289190611b4e565b610637565b60405161023a9190611c24565b60405180910390f35b61025d600480360381019061025891906115c8565b610799565b60405161026a9190611808565b60405180910390f35b61028d60048036038101906102889190611c9c565b6107f3565b60405161029a9190611808565b60405180910390f35b6102bd60048036038101906102b89190611d74565b610869565b005b6102d960048036038101906102d49190611de3565b6108b9565b6040516102e69190611685565b60405180910390f35b610309600480360381019061030491906115c8565b6109d5565b005b6060600061031883610a58565b9050600360006004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000828152602001908152602001600020805461038490611e6e565b80601f01602080910402602001604051908101604052809291908181526020018280546103b090611e6e565b80156103fd5780601f106103d2576101008083540402835291602001916103fd565b820191906000526020600020905b8154815290600101906020018083116103e057829003601f168201915b5050505050915050919050565b60007fd8efbe27000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104d557507f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806104e557506104e482610ab7565b5b9050919050565b60016020528060005260406000206000915090505481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610554610b21565b61055e6000610b9f565b565b6000637f87032e60e01b8460405160200161057c929190611efc565b604051602081830303815290604052805190602001208584846105a184848484610c63565b5060006105ad8a610a58565b90506105ba818a8a610d7b565b808a73ffffffffffffffffffffffffffffffffffffffff167f6ada868dd3058cf77a48a74489fd7963688e5464b2b0fa957ace976243270e9260405160405180910390a38095505050505050949350505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008383906106489190611f3c565b905060006106a887878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286106a39190611fca565b610e2f565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610709576107008161030b565b92505050610791565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361078e5760008585600490809261076a93929190612008565b8101906107779190612043565b91505061078482826108b9565b9350505050610791565b50505b949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006107c583610e78565b6040516020016107d69291906120c0565b604051602081830303815290604052805190602001209050919050565b600063c01f93d360e01b87878787604051602001610815959493929190612111565b6040516020818303038152906040528051906020012088848461083a84848484610c63565b5060006108468d610a58565b9050610856818d8d8d8d8d610f00565b8095505050505050979650505050505050565b63c7ee930c60e01b604051602001610881919061214a565b604051602081830303815290604052805190602001208383836108a684848484610c63565b506108b087610ff5565b50505050505050565b606060006108c684610a58565b9050600260006004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000828152602001908152602001600020836040516109359190612165565b9081526020016040518091039020805461094e90611e6e565b80601f016020809104026020016040519081016040528092919081815260200182805461097a90611e6e565b80156109c75780601f1061099c576101008083540402835291602001916109c7565b820191906000526020600020905b8154815290600101906020018083116109aa57829003601f168201915b505050505091505092915050565b6109dd610b21565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a43906121ee565b60405180910390fd5b610a5581610b9f565b50565b600080610a6483610e78565b90507f000000000000000000000000000000000000000000000000000000000000000081604051602001610a999291906120c0565b60405160208183030381529060405280519060200120915050919050565b60007fc78de5ed000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610b29611111565b73ffffffffffffffffffffffffffffffffffffffff16610b4761060e565b73ffffffffffffffffffffffffffffffffffffffff1614610b9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b949061225a565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080610cbb8686867f0000000000000000000000000000000000000000000000000000000000000000604051602001610ca094939291906122e3565b60405160208183030381529060405280519060200120611119565b90506000610cc886610a58565b9050610cd586838661114f565b610d0b576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008281526020019081526020016000205485111580610d3a5750426103e886610d379190612360565b10155b15610d71576040517f50c8f2ec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050949350505050565b81600360006004600087815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008581526020019081526020016000209081610de79190612530565b50610df283826111de565b827fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f783604051610e229190611685565b60405180910390a2505050565b60008060288484610e409190612602565b1015610e525760008091509150610e70565b600080610e608787876111fa565b915091508160001c819350935050505b935093915050565b600060285b6000811115610ef3576001810390507f3031323334353637383961626364656600000000000000000000000000000000600f84161a81536010830492506001810390507f3031323334353637383961626364656600000000000000000000000000000000600f84161a8153601083049250610e7d565b5060286000209050919050565b828260026000600460008b815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008981526020019081526020016000208787604051610f71929190612636565b90815260200160405180910390209182610f8c92919061265a565b50610f9786826111de565b8484604051610fa7929190612636565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a187878787604051610fe59493929190612757565b60405180910390a3505050505050565b600061100082610e78565b905060007f0000000000000000000000000000000000000000000000000000000000000000826040516020016110379291906120c0565b60405160208183030381529060405280519060200120905060046000828152602001908152602001600020600081819054906101000a900467ffffffffffffffff1680929190611086906127a6565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050807fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db4446004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1660405161110491906127e5565b60405180910390a2505050565b600033905090565b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005281601c52603c6000209050919050565b600080600061115e85856112df565b915091506000600481111561117657611175612800565b5b81600481111561118957611188612800565b5b1480156111c157508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806111d357506111d2868686611330565b5b925050509392505050565b8060016000848152602001908152602001600020819055505050565b60008060019050845183111561120f57600080fd5b611271565b6000603a8210602f8311161561122f5760308203905061126c565b6047821060408311161561124b57600a6041830301905061126c565b6067821060608311161561126757600a6061830301905061126c565b60ff90505b919050565b60208501845b848110156112d55761128e8183015160001a611214565b6112a06001830184015160001a611214565b60ff811460ff831417156112b9576000945050506112d5565b808260041b17808760081b179650505050600281019050611277565b5050935093915050565b60008060418351036113205760008060006020860151925060408601519150606086015160001a905061131487828585611474565b94509450505050611329565b60006002915091505b9250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b868660405160240161136792919061282f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516113d1919061289b565b600060405180830381855afa9150503d806000811461140c576040519150601f19603f3d011682016040523d82523d6000602084013e611411565b606091505b509150915081801561142557506020815110155b80156114695750631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168180602001905181019061146791906128c7565b145b925050509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156114af57600060039150915061154d565b6000600187878787604051600081526020016040526040516114d49493929190612910565b6020604051602081039080840390855afa1580156114f6573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115445760006001925092505061154d565b80600092509250505b94509492505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006115958261156a565b9050919050565b6115a58161158a565b81146115b057600080fd5b50565b6000813590506115c28161159c565b92915050565b6000602082840312156115de576115dd611560565b5b60006115ec848285016115b3565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561162f578082015181840152602081019050611614565b60008484015250505050565b6000601f19601f8301169050919050565b6000611657826115f5565b6116618185611600565b9350611671818560208601611611565b61167a8161163b565b840191505092915050565b6000602082019050818103600083015261169f818461164c565b905092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6116dc816116a7565b81146116e757600080fd5b50565b6000813590506116f9816116d3565b92915050565b60006020828403121561171557611714611560565b5b6000611723848285016116ea565b91505092915050565b60008115159050919050565b6117418161172c565b82525050565b600060208201905061175c6000830184611738565b92915050565b6000819050919050565b61177581611762565b811461178057600080fd5b50565b6000813590506117928161176c565b92915050565b6000602082840312156117ae576117ad611560565b5b60006117bc84828501611783565b91505092915050565b6000819050919050565b6117d8816117c5565b82525050565b60006020820190506117f360008301846117cf565b92915050565b61180281611762565b82525050565b600060208201905061181d60008301846117f9565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6118658261163b565b810181811067ffffffffffffffff821117156118845761188361182d565b5b80604052505050565b6000611897611556565b90506118a3828261185c565b919050565b600067ffffffffffffffff8211156118c3576118c261182d565b5b6118cc8261163b565b9050602081019050919050565b82818337600083830152505050565b60006118fb6118f6846118a8565b61188d565b90508281526020810184848401111561191757611916611828565b5b6119228482856118d9565b509392505050565b600082601f83011261193f5761193e611823565b5b813561194f8482602086016118e8565b91505092915050565b611961816117c5565b811461196c57600080fd5b50565b60008135905061197e81611958565b92915050565b600067ffffffffffffffff82111561199f5761199e61182d565b5b6119a88261163b565b9050602081019050919050565b60006119c86119c384611984565b61188d565b9050828152602081018484840111156119e4576119e3611828565b5b6119ef8482856118d9565b509392505050565b600082601f830112611a0c57611a0b611823565b5b8135611a1c8482602086016119b5565b91505092915050565b60008060008060808587031215611a3f57611a3e611560565b5b6000611a4d878288016115b3565b945050602085013567ffffffffffffffff811115611a6e57611a6d611565565b5b611a7a8782880161192a565b9350506040611a8b8782880161196f565b925050606085013567ffffffffffffffff811115611aac57611aab611565565b5b611ab8878288016119f7565b91505092959194509250565b611acd8161158a565b82525050565b6000602082019050611ae86000830184611ac4565b92915050565b600080fd5b600080fd5b60008083601f840112611b0e57611b0d611823565b5b8235905067ffffffffffffffff811115611b2b57611b2a611aee565b5b602083019150836001820283011115611b4757611b46611af3565b5b9250929050565b60008060008060408587031215611b6857611b67611560565b5b600085013567ffffffffffffffff811115611b8657611b85611565565b5b611b9287828801611af8565b9450945050602085013567ffffffffffffffff811115611bb557611bb4611565565b5b611bc187828801611af8565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000611bf682611bcf565b611c008185611bda565b9350611c10818560208601611611565b611c198161163b565b840191505092915050565b60006020820190508181036000830152611c3e8184611beb565b905092915050565b60008083601f840112611c5c57611c5b611823565b5b8235905067ffffffffffffffff811115611c7957611c78611aee565b5b602083019150836001820283011115611c9557611c94611af3565b5b9250929050565b600080600080600080600060a0888a031215611cbb57611cba611560565b5b6000611cc98a828b016115b3565b975050602088013567ffffffffffffffff811115611cea57611ce9611565565b5b611cf68a828b01611c46565b9650965050604088013567ffffffffffffffff811115611d1957611d18611565565b5b611d258a828b01611c46565b94509450506060611d388a828b0161196f565b925050608088013567ffffffffffffffff811115611d5957611d58611565565b5b611d658a828b016119f7565b91505092959891949750929550565b600080600060608486031215611d8d57611d8c611560565b5b6000611d9b868287016115b3565b9350506020611dac8682870161196f565b925050604084013567ffffffffffffffff811115611dcd57611dcc611565565b5b611dd9868287016119f7565b9150509250925092565b60008060408385031215611dfa57611df9611560565b5b6000611e08858286016115b3565b925050602083013567ffffffffffffffff811115611e2957611e28611565565b5b611e358582860161192a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e8657607f821691505b602082108103611e9957611e98611e3f565b5b50919050565b6000819050919050565b611eba611eb5826116a7565b611e9f565b82525050565b600081905092915050565b6000611ed6826115f5565b611ee08185611ec0565b9350611ef0818560208601611611565b80840191505092915050565b6000611f088285611ea9565b600482019150611f188284611ecb565b91508190509392505050565b600082905092915050565b600082821b905092915050565b6000611f488383611f24565b82611f5381356116a7565b92506004821015611f9357611f8e7fffffffff0000000000000000000000000000000000000000000000000000000083600403600802611f2f565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611fd5826117c5565b9150611fe0836117c5565b9250828201905080821115611ff857611ff7611f9b565b5b92915050565b600080fd5b600080fd5b6000808585111561201c5761201b611ffe565b5b8386111561202d5761202c612003565b5b6001850283019150848603905094509492505050565b6000806040838503121561205a57612059611560565b5b600061206885828601611783565b925050602083013567ffffffffffffffff81111561208957612088611565565b5b6120958582860161192a565b9150509250929050565b6000819050919050565b6120ba6120b582611762565b61209f565b82525050565b60006120cc82856120a9565b6020820191506120dc82846120a9565b6020820191508190509392505050565b60006120f88385611ec0565b93506121058385846118d9565b82840190509392505050565b600061211d8288611ea9565b60048201915061212e8286886120ec565b915061213b8284866120ec565b91508190509695505050505050565b60006121568284611ea9565b60048201915081905092915050565b60006121718284611ecb565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006121d8602683611600565b91506121e38261217c565b604082019050919050565b60006020820190508181036000830152612207816121cb565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612244602083611600565b915061224f8261220e565b602082019050919050565b6000602082019050818103600083015261227381612237565b9050919050565b60008160601b9050919050565b60006122928261227a565b9050919050565b60006122a482612287565b9050919050565b6122bc6122b78261158a565b612299565b82525050565b6000819050919050565b6122dd6122d8826117c5565b6122c2565b82525050565b60006122ef82876120a9565b6020820191506122ff82866122ab565b60148201915061230f82856122cc565b60208201915061231f82846122cc565b60208201915081905095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061236b826117c5565b9150612376836117c5565b92508261238657612385612331565b5b828204905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b6000600883026123e67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611f2f565b6123f08683611f2f565b95508019841693508086168417925050509392505050565b6000819050919050565b600061242d612428612423846117c5565b612408565b6117c5565b9050919050565b6000819050919050565b61244783612412565b61245b61245382612434565b8484546123b6565b825550505050565b600090565b612470612463565b61247b81848461243e565b505050565b5b8181101561249f57612494600082612468565b600181019050612481565b5050565b601f8211156124e4576124b581612391565b6124be846123a6565b810160208510156124cd578190505b6124e16124d9856123a6565b830182612480565b50505b505050565b600082821c905092915050565b6000612507600019846008026124e9565b1980831691505092915050565b600061252083836124f6565b9150826002028217905092915050565b612539826115f5565b67ffffffffffffffff8111156125525761255161182d565b5b61255c8254611e6e565b6125678282856124a3565b600060209050601f83116001811461259a5760008415612588578287015190505b6125928582612514565b8655506125fa565b601f1984166125a886612391565b60005b828110156125d0578489015182556001820191506020850194506020810190506125ab565b868310156125ed57848901516125e9601f8916826124f6565b8355505b6001600288020188555050505b505050505050565b600061260d826117c5565b9150612618836117c5565b92508282039050818111156126305761262f611f9b565b5b92915050565b60006126438284866120ec565b91508190509392505050565b600082905092915050565b612664838361264f565b67ffffffffffffffff81111561267d5761267c61182d565b5b6126878254611e6e565b6126928282856124a3565b6000601f8311600181146126c157600084156126af578287013590505b6126b98582612514565b865550612721565b601f1984166126cf86612391565b60005b828110156126f7578489013582556001820191506020850194506020810190506126d2565b868310156127145784890135612710601f8916826124f6565b8355505b6001600288020188555050505b50505050505050565b60006127368385611600565b93506127438385846118d9565b61274c8361163b565b840190509392505050565b6000604082019050818103600083015261277281868861272a565b9050818103602083015261278781848661272a565b905095945050505050565b600067ffffffffffffffff82169050919050565b60006127b182612792565b915067ffffffffffffffff82036127cb576127ca611f9b565b5b600182019050919050565b6127df81612792565b82525050565b60006020820190506127fa60008301846127d6565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060408201905061284460008301856117f9565b81810360208301526128568184611beb565b90509392505050565b600081905092915050565b600061287582611bcf565b61287f818561285f565b935061288f818560208601611611565b80840191505092915050565b60006128a7828461286a565b915081905092915050565b6000815190506128c18161176c565b92915050565b6000602082840312156128dd576128dc611560565b5b60006128eb848285016128b2565b91505092915050565b600060ff82169050919050565b61290a816128f4565b82525050565b600060808201905061292560008301876117f9565b6129326020830186612901565b61293f60408301856117f9565b61294c60608301846117f9565b9594505050505056fea264697066735822122064d056b576c53f15f918ab0cbc8cd9058c15fddb5e164956c854c85d5141f05664736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063c01f93d311610066578063c01f93d314610273578063c7ee930c146102a3578063d977f6b5146102bf578063f2fde38b146102ef576100ea565b80638da5cb5b146101f55780639061b92314610213578063bffbe61c14610243576100ea565b80631fe93ea8116100c85780631fe93ea81461017f57806324d79eab1461019d578063715018a6146101bb5780637f87032e146101c5576100ea565b806301984892146100ef57806301ffc9a71461011f578063060eb2f51461014f575b600080fd5b610109600480360381019061010491906115c8565b61030b565b6040516101169190611685565b60405180910390f35b610139600480360381019061013491906116ff565b61040a565b6040516101469190611747565b60405180910390f35b61016960048036038101906101649190611798565b6104ec565b60405161017691906117de565b60405180910390f35b610187610504565b60405161019491906117de565b60405180910390f35b6101a5610528565b6040516101b29190611808565b60405180910390f35b6101c361054c565b005b6101df60048036038101906101da9190611a25565b610560565b6040516101ec9190611808565b60405180910390f35b6101fd61060e565b60405161020a9190611ad3565b60405180910390f35b61022d60048036038101906102289190611b4e565b610637565b60405161023a9190611c24565b60405180910390f35b61025d600480360381019061025891906115c8565b610799565b60405161026a9190611808565b60405180910390f35b61028d60048036038101906102889190611c9c565b6107f3565b60405161029a9190611808565b60405180910390f35b6102bd60048036038101906102b89190611d74565b610869565b005b6102d960048036038101906102d49190611de3565b6108b9565b6040516102e69190611685565b60405180910390f35b610309600480360381019061030491906115c8565b6109d5565b005b6060600061031883610a58565b9050600360006004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000828152602001908152602001600020805461038490611e6e565b80601f01602080910402602001604051908101604052809291908181526020018280546103b090611e6e565b80156103fd5780601f106103d2576101008083540402835291602001916103fd565b820191906000526020600020905b8154815290600101906020018083116103e057829003601f168201915b5050505050915050919050565b60007fd8efbe27000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104d557507f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806104e557506104e482610ab7565b5b9050919050565b60016020528060005260406000206000915090505481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610554610b21565b61055e6000610b9f565b565b6000637f87032e60e01b8460405160200161057c929190611efc565b604051602081830303815290604052805190602001208584846105a184848484610c63565b5060006105ad8a610a58565b90506105ba818a8a610d7b565b808a73ffffffffffffffffffffffffffffffffffffffff167f6ada868dd3058cf77a48a74489fd7963688e5464b2b0fa957ace976243270e9260405160405180910390a38095505050505050949350505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008383906106489190611f3c565b905060006106a887878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286106a39190611fca565b610e2f565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610709576107008161030b565b92505050610791565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19160361078e5760008585600490809261076a93929190612008565b8101906107779190612043565b91505061078482826108b9565b9350505050610791565b50505b949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006107c583610e78565b6040516020016107d69291906120c0565b604051602081830303815290604052805190602001209050919050565b600063c01f93d360e01b87878787604051602001610815959493929190612111565b6040516020818303038152906040528051906020012088848461083a84848484610c63565b5060006108468d610a58565b9050610856818d8d8d8d8d610f00565b8095505050505050979650505050505050565b63c7ee930c60e01b604051602001610881919061214a565b604051602081830303815290604052805190602001208383836108a684848484610c63565b506108b087610ff5565b50505050505050565b606060006108c684610a58565b9050600260006004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206000828152602001908152602001600020836040516109359190612165565b9081526020016040518091039020805461094e90611e6e565b80601f016020809104026020016040519081016040528092919081815260200182805461097a90611e6e565b80156109c75780601f1061099c576101008083540402835291602001916109c7565b820191906000526020600020905b8154815290600101906020018083116109aa57829003601f168201915b505050505091505092915050565b6109dd610b21565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610a4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a43906121ee565b60405180910390fd5b610a5581610b9f565b50565b600080610a6483610e78565b90507f000000000000000000000000000000000000000000000000000000000000000081604051602001610a999291906120c0565b60405160208183030381529060405280519060200120915050919050565b60007fc78de5ed000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610b29611111565b73ffffffffffffffffffffffffffffffffffffffff16610b4761060e565b73ffffffffffffffffffffffffffffffffffffffff1614610b9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b949061225a565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080610cbb8686867f0000000000000000000000000000000000000000000000000000000000000000604051602001610ca094939291906122e3565b60405160208183030381529060405280519060200120611119565b90506000610cc886610a58565b9050610cd586838661114f565b610d0b576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008281526020019081526020016000205485111580610d3a5750426103e886610d379190612360565b10155b15610d71576040517f50c8f2ec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050949350505050565b81600360006004600087815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008581526020019081526020016000209081610de79190612530565b50610df283826111de565b827fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f783604051610e229190611685565b60405180910390a2505050565b60008060288484610e409190612602565b1015610e525760008091509150610e70565b600080610e608787876111fa565b915091508160001c819350935050505b935093915050565b600060285b6000811115610ef3576001810390507f3031323334353637383961626364656600000000000000000000000000000000600f84161a81536010830492506001810390507f3031323334353637383961626364656600000000000000000000000000000000600f84161a8153601083049250610e7d565b5060286000209050919050565b828260026000600460008b815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008981526020019081526020016000208787604051610f71929190612636565b90815260200160405180910390209182610f8c92919061265a565b50610f9786826111de565b8484604051610fa7929190612636565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a187878787604051610fe59493929190612757565b60405180910390a3505050505050565b600061100082610e78565b905060007f0000000000000000000000000000000000000000000000000000000000000000826040516020016110379291906120c0565b60405160208183030381529060405280519060200120905060046000828152602001908152602001600020600081819054906101000a900467ffffffffffffffff1680929190611086906127a6565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050807fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db4446004600084815260200190815260200160002060009054906101000a900467ffffffffffffffff1660405161110491906127e5565b60405180910390a2505050565b600033905090565b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005281601c52603c6000209050919050565b600080600061115e85856112df565b915091506000600481111561117657611175612800565b5b81600481111561118957611188612800565b5b1480156111c157508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806111d357506111d2868686611330565b5b925050509392505050565b8060016000848152602001908152602001600020819055505050565b60008060019050845183111561120f57600080fd5b611271565b6000603a8210602f8311161561122f5760308203905061126c565b6047821060408311161561124b57600a6041830301905061126c565b6067821060608311161561126757600a6061830301905061126c565b60ff90505b919050565b60208501845b848110156112d55761128e8183015160001a611214565b6112a06001830184015160001a611214565b60ff811460ff831417156112b9576000945050506112d5565b808260041b17808760081b179650505050600281019050611277565b5050935093915050565b60008060418351036113205760008060006020860151925060408601519150606086015160001a905061131487828585611474565b94509450505050611329565b60006002915091505b9250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b868660405160240161136792919061282f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516113d1919061289b565b600060405180830381855afa9150503d806000811461140c576040519150601f19603f3d011682016040523d82523d6000602084013e611411565b606091505b509150915081801561142557506020815110155b80156114695750631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168180602001905181019061146791906128c7565b145b925050509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156114af57600060039150915061154d565b6000600187878787604051600081526020016040526040516114d49493929190612910565b6020604051602081039080840390855afa1580156114f6573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115445760006001925092505061154d565b80600092509250505b94509492505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006115958261156a565b9050919050565b6115a58161158a565b81146115b057600080fd5b50565b6000813590506115c28161159c565b92915050565b6000602082840312156115de576115dd611560565b5b60006115ec848285016115b3565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561162f578082015181840152602081019050611614565b60008484015250505050565b6000601f19601f8301169050919050565b6000611657826115f5565b6116618185611600565b9350611671818560208601611611565b61167a8161163b565b840191505092915050565b6000602082019050818103600083015261169f818461164c565b905092915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6116dc816116a7565b81146116e757600080fd5b50565b6000813590506116f9816116d3565b92915050565b60006020828403121561171557611714611560565b5b6000611723848285016116ea565b91505092915050565b60008115159050919050565b6117418161172c565b82525050565b600060208201905061175c6000830184611738565b92915050565b6000819050919050565b61177581611762565b811461178057600080fd5b50565b6000813590506117928161176c565b92915050565b6000602082840312156117ae576117ad611560565b5b60006117bc84828501611783565b91505092915050565b6000819050919050565b6117d8816117c5565b82525050565b60006020820190506117f360008301846117cf565b92915050565b61180281611762565b82525050565b600060208201905061181d60008301846117f9565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6118658261163b565b810181811067ffffffffffffffff821117156118845761188361182d565b5b80604052505050565b6000611897611556565b90506118a3828261185c565b919050565b600067ffffffffffffffff8211156118c3576118c261182d565b5b6118cc8261163b565b9050602081019050919050565b82818337600083830152505050565b60006118fb6118f6846118a8565b61188d565b90508281526020810184848401111561191757611916611828565b5b6119228482856118d9565b509392505050565b600082601f83011261193f5761193e611823565b5b813561194f8482602086016118e8565b91505092915050565b611961816117c5565b811461196c57600080fd5b50565b60008135905061197e81611958565b92915050565b600067ffffffffffffffff82111561199f5761199e61182d565b5b6119a88261163b565b9050602081019050919050565b60006119c86119c384611984565b61188d565b9050828152602081018484840111156119e4576119e3611828565b5b6119ef8482856118d9565b509392505050565b600082601f830112611a0c57611a0b611823565b5b8135611a1c8482602086016119b5565b91505092915050565b60008060008060808587031215611a3f57611a3e611560565b5b6000611a4d878288016115b3565b945050602085013567ffffffffffffffff811115611a6e57611a6d611565565b5b611a7a8782880161192a565b9350506040611a8b8782880161196f565b925050606085013567ffffffffffffffff811115611aac57611aab611565565b5b611ab8878288016119f7565b91505092959194509250565b611acd8161158a565b82525050565b6000602082019050611ae86000830184611ac4565b92915050565b600080fd5b600080fd5b60008083601f840112611b0e57611b0d611823565b5b8235905067ffffffffffffffff811115611b2b57611b2a611aee565b5b602083019150836001820283011115611b4757611b46611af3565b5b9250929050565b60008060008060408587031215611b6857611b67611560565b5b600085013567ffffffffffffffff811115611b8657611b85611565565b5b611b9287828801611af8565b9450945050602085013567ffffffffffffffff811115611bb557611bb4611565565b5b611bc187828801611af8565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000611bf682611bcf565b611c008185611bda565b9350611c10818560208601611611565b611c198161163b565b840191505092915050565b60006020820190508181036000830152611c3e8184611beb565b905092915050565b60008083601f840112611c5c57611c5b611823565b5b8235905067ffffffffffffffff811115611c7957611c78611aee565b5b602083019150836001820283011115611c9557611c94611af3565b5b9250929050565b600080600080600080600060a0888a031215611cbb57611cba611560565b5b6000611cc98a828b016115b3565b975050602088013567ffffffffffffffff811115611cea57611ce9611565565b5b611cf68a828b01611c46565b9650965050604088013567ffffffffffffffff811115611d1957611d18611565565b5b611d258a828b01611c46565b94509450506060611d388a828b0161196f565b925050608088013567ffffffffffffffff811115611d5957611d58611565565b5b611d658a828b016119f7565b91505092959891949750929550565b600080600060608486031215611d8d57611d8c611560565b5b6000611d9b868287016115b3565b9350506020611dac8682870161196f565b925050604084013567ffffffffffffffff811115611dcd57611dcc611565565b5b611dd9868287016119f7565b9150509250925092565b60008060408385031215611dfa57611df9611560565b5b6000611e08858286016115b3565b925050602083013567ffffffffffffffff811115611e2957611e28611565565b5b611e358582860161192a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e8657607f821691505b602082108103611e9957611e98611e3f565b5b50919050565b6000819050919050565b611eba611eb5826116a7565b611e9f565b82525050565b600081905092915050565b6000611ed6826115f5565b611ee08185611ec0565b9350611ef0818560208601611611565b80840191505092915050565b6000611f088285611ea9565b600482019150611f188284611ecb565b91508190509392505050565b600082905092915050565b600082821b905092915050565b6000611f488383611f24565b82611f5381356116a7565b92506004821015611f9357611f8e7fffffffff0000000000000000000000000000000000000000000000000000000083600403600802611f2f565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611fd5826117c5565b9150611fe0836117c5565b9250828201905080821115611ff857611ff7611f9b565b5b92915050565b600080fd5b600080fd5b6000808585111561201c5761201b611ffe565b5b8386111561202d5761202c612003565b5b6001850283019150848603905094509492505050565b6000806040838503121561205a57612059611560565b5b600061206885828601611783565b925050602083013567ffffffffffffffff81111561208957612088611565565b5b6120958582860161192a565b9150509250929050565b6000819050919050565b6120ba6120b582611762565b61209f565b82525050565b60006120cc82856120a9565b6020820191506120dc82846120a9565b6020820191508190509392505050565b60006120f88385611ec0565b93506121058385846118d9565b82840190509392505050565b600061211d8288611ea9565b60048201915061212e8286886120ec565b915061213b8284866120ec565b91508190509695505050505050565b60006121568284611ea9565b60048201915081905092915050565b60006121718284611ecb565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006121d8602683611600565b91506121e38261217c565b604082019050919050565b60006020820190508181036000830152612207816121cb565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000612244602083611600565b915061224f8261220e565b602082019050919050565b6000602082019050818103600083015261227381612237565b9050919050565b60008160601b9050919050565b60006122928261227a565b9050919050565b60006122a482612287565b9050919050565b6122bc6122b78261158a565b612299565b82525050565b6000819050919050565b6122dd6122d8826117c5565b6122c2565b82525050565b60006122ef82876120a9565b6020820191506122ff82866122ab565b60148201915061230f82856122cc565b60208201915061231f82846122cc565b60208201915081905095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061236b826117c5565b9150612376836117c5565b92508261238657612385612331565b5b828204905092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b6000600883026123e67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611f2f565b6123f08683611f2f565b95508019841693508086168417925050509392505050565b6000819050919050565b600061242d612428612423846117c5565b612408565b6117c5565b9050919050565b6000819050919050565b61244783612412565b61245b61245382612434565b8484546123b6565b825550505050565b600090565b612470612463565b61247b81848461243e565b505050565b5b8181101561249f57612494600082612468565b600181019050612481565b5050565b601f8211156124e4576124b581612391565b6124be846123a6565b810160208510156124cd578190505b6124e16124d9856123a6565b830182612480565b50505b505050565b600082821c905092915050565b6000612507600019846008026124e9565b1980831691505092915050565b600061252083836124f6565b9150826002028217905092915050565b612539826115f5565b67ffffffffffffffff8111156125525761255161182d565b5b61255c8254611e6e565b6125678282856124a3565b600060209050601f83116001811461259a5760008415612588578287015190505b6125928582612514565b8655506125fa565b601f1984166125a886612391565b60005b828110156125d0578489015182556001820191506020850194506020810190506125ab565b868310156125ed57848901516125e9601f8916826124f6565b8355505b6001600288020188555050505b505050505050565b600061260d826117c5565b9150612618836117c5565b92508282039050818111156126305761262f611f9b565b5b92915050565b60006126438284866120ec565b91508190509392505050565b600082905092915050565b612664838361264f565b67ffffffffffffffff81111561267d5761267c61182d565b5b6126878254611e6e565b6126928282856124a3565b6000601f8311600181146126c157600084156126af578287013590505b6126b98582612514565b865550612721565b601f1984166126cf86612391565b60005b828110156126f7578489013582556001820191506020850194506020810190506126d2565b868310156127145784890135612710601f8916826124f6565b8355505b6001600288020188555050505b50505050505050565b60006127368385611600565b93506127438385846118d9565b61274c8361163b565b840190509392505050565b6000604082019050818103600083015261277281868861272a565b9050818103602083015261278781848661272a565b905095945050505050565b600067ffffffffffffffff82169050919050565b60006127b182612792565b915067ffffffffffffffff82036127cb576127ca611f9b565b5b600182019050919050565b6127df81612792565b82525050565b60006020820190506127fa60008301846127d6565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060408201905061284460008301856117f9565b81810360208301526128568184611beb565b90509392505050565b600081905092915050565b600061287582611bcf565b61287f818561285f565b935061288f818560208601611611565b80840191505092915050565b60006128a7828461286a565b915081905092915050565b6000815190506128c18161176c565b92915050565b6000602082840312156128dd576128dc611560565b5b60006128eb848285016128b2565b91505092915050565b600060ff82169050919050565b61290a816128f4565b82525050565b600060808201905061292560008301876117f9565b6129326020830186612901565b61293f60408301856117f9565b61294c60608301846117f9565b9594505050505056fea264697066735822122064d056b576c53f15f918ab0cbc8cd9058c15fddb5e164956c854c85d5141f05664736f6c63430008130033", + "devdoc": { + "kind": "dev", + "methods": { + "clearRecordsWithSignature(address,uint256,bytes)": { + "params": { + "addr": "The node to update.", + "signature": "A signature proving ownership of the node." + } + }, + "constructor": { + "details": "Constructor" + }, + "node(address)": { + "details": "Returns the node hash for a given account's reverse records.", + "params": { + "addr": "The address to hash" + }, + "returns": { + "_0": "The ENS node hash." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setNameForAddrWithSignature(address,string,uint256,bytes)": { + "details": "Sets the name for an addr using a signature that can be verified with ERC1271.", + "params": { + "addr": "The reverse record to set", + "inceptionDate": "Date from when this signature is valid from", + "name": "The name of the reverse record", + "signature": "The resolver of the reverse node" + }, + "returns": { + "_0": "The ENS node hash of the reverse record." + } + }, + "setTextForAddrWithSignature(address,string,string,uint256,bytes)": { + "details": "Sets the name for an addr using a signature that can be verified with ERC1271.", + "params": { + "addr": "The reverse record to set", + "inceptionDate": "Date from when this signature is valid from", + "key": "The key of the text record", + "signature": "The resolver of the reverse node", + "value": "The value of the text record" + }, + "returns": { + "_0": "The ENS node hash of the reverse record." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "clearRecordsWithSignature(address,uint256,bytes)": { + "notice": "Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry." + } + }, + "notice": "A fallback reverser resolver to resolve when L2 reverse resolver has no names set. The contract will be set under \"default.reverse\" namespace It can only be set by EOA as contract accounts are chain dependent.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1121, + "contract": "contracts/DefaultReverseResolver.sol:DefaultReverseResolver", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 289, + "contract": "contracts/DefaultReverseResolver.sol:DefaultReverseResolver", + "label": "lastUpdated", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + }, + { + "astId": 297, + "contract": "contracts/DefaultReverseResolver.sol:DefaultReverseResolver", + "label": "versionable_texts", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))" + }, + { + "astId": 303, + "contract": "contracts/DefaultReverseResolver.sol:DefaultReverseResolver", + "label": "versionable_names", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))" + }, + { + "astId": 307, + "contract": "contracts/DefaultReverseResolver.sol:DefaultReverseResolver", + "label": "recordVersions", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes32,t_uint64)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(string => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_string_memory_ptr,t_string_storage)" + }, + "t_mapping(t_bytes32,t_string_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_mapping(t_string_memory_ptr,t_string_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(string => string)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_string_storage)" + }, + "t_string_memory_ptr": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + } +} \ No newline at end of file diff --git a/crosschain-reverse-resolver/deployments/sepolia/OpL1ReverseResolver.json b/crosschain-reverse-resolver/deployments/sepolia/OpL1ReverseResolver.json index 0e81a9b9..95b42dec 100644 --- a/crosschain-reverse-resolver/deployments/sepolia/OpL1ReverseResolver.json +++ b/crosschain-reverse-resolver/deployments/sepolia/OpL1ReverseResolver.json @@ -1,5 +1,5 @@ { - "address": "0xCCe95773C00b924c9EB60822c970eBA2884Ef6A3", + "address": "0xF7e3a2861FfA833C39544B7bbE9D94f3219E5b70", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "address", "name": "_target", "type": "address" + }, + { + "internalType": "contract IDefaultReverseResolver", + "name": "_defaultReverseResolver", + "type": "address" } ], "stateMutability": "nonpayable", @@ -96,56 +101,6 @@ "name": "TooManyCommands", "type": "error" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "NameChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "string", - "name": "indexedKey", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "value", - "type": "string" - } - ], - "name": "TextChanged", - "type": "event" - }, { "inputs": [ { @@ -167,12 +122,17 @@ { "inputs": [ { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "callbackdata", + "type": "bytes" } ], - "name": "name", + "name": "nameCallback", "outputs": [ { "internalType": "string", @@ -186,25 +146,25 @@ { "inputs": [ { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" + "internalType": "bytes", + "name": "name", + "type": "bytes" }, { "internalType": "bytes", - "name": "", + "name": "data", "type": "bytes" } ], - "name": "nameCallback", + "name": "resolve", "outputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "bytes", + "name": "result", + "type": "bytes" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -226,30 +186,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "key", - "type": "string" - } - ], - "name": "text", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -259,7 +195,7 @@ }, { "internalType": "bytes", - "name": "", + "name": "callbackdata", "type": "bytes" } ], @@ -271,74 +207,61 @@ "type": "string" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" } ], - "transactionHash": "0x70adfd4afd822457c65e4a0765a39f569185a619a9d9a94b8b6d1a795849b8af", + "transactionHash": "0x9eac452321494e39dd3b63fcddb8c5644ac235916c8bda64712e06d77d8d317b", "receipt": { "to": null, "from": "0xDBBC2C0fe2a1D0fB4056B35a22e543bEb715E7FC", - "contractAddress": "0xCCe95773C00b924c9EB60822c970eBA2884Ef6A3", - "transactionIndex": 103, - "gasUsed": "2087308", + "contractAddress": "0xF7e3a2861FfA833C39544B7bbE9D94f3219E5b70", + "transactionIndex": 96, + "gasUsed": "2427859", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x70c9f60dab82e9cacf7cb7451a6ef6dd115c5b5c927643312c1941987f2df1d0", - "transactionHash": "0x70adfd4afd822457c65e4a0765a39f569185a619a9d9a94b8b6d1a795849b8af", + "blockHash": "0x4fef4f8be6b37ce03c137f32111da27ea3bf4f176958d0cdac6554132cc3910e", + "transactionHash": "0x9eac452321494e39dd3b63fcddb8c5644ac235916c8bda64712e06d77d8d317b", "logs": [], - "blockNumber": 5132853, - "cumulativeGasUsed": "15084879", + "blockNumber": 5347090, + "cumulativeGasUsed": "10054565", "status": 1, "byzantium": true }, "args": [ "0x0e8DA38565915B7e74e2d78F80ba1BF815F34116", - "0xfdF30e5E06d728704A42bac6E0326538E659a67B" + "0x83C058D2139a6eFA32E42BeB415409000C075563", + "0xfD2c2598382D8876BcC70f550B22d7F70Dda30b0" ], - "numDeployments": 2, - "solcInputHash": "82230a92851c1800498f571d3f1bd7cb", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"name(bytes32)\":{\"notice\":\"Returns the address associated with an ENS node.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, INameResolver, ITextResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n \\n constructor(IEVMVerifier _verifier, address _target) {\\n verifier = _verifier;\\n target = _target;\\n }\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n // return versionable_names[recordVersions[node]][node];\\n function name(bytes32 node) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, ''); // recordVersions\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\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 ) public view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, '');\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory\\n ) public pure returns (string memory) {\\n return string(values[1]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(ITextResolver).interfaceId ||\\n interfaceId == type(INameResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0x99abd98e4a517ecbfc9f14f970dbeec2417de4184c0996163831c2e9faf25a9d\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200269a3803806200269a833981810160405281019062000037919062000156565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505050506200019d565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000d982620000ac565b9050919050565b6000620000ed82620000cc565b9050919050565b620000ff81620000e0565b81146200010b57600080fd5b50565b6000815190506200011f81620000f4565b92915050565b6200013081620000cc565b81146200013c57600080fd5b50565b600081519050620001508162000125565b92915050565b6000806040838503121562000170576200016f620000a7565b5b600062000180858286016200010e565b925050602062000193858286016200013f565b9150509250929050565b60805160a0516124c9620001d16000396000818161031d01526105b40152600081816102fc015261059301526124c96000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780632682dd661461009757806359d1d43c146100c75780635bdaa916146100f7578063691f343114610113578063de9abe5e14610143575b600080fd5b610081600480360381019061007c919061106b565b610173565b60405161008e91906110b3565b60405180910390f35b6100b160048036038101906100ac91906112fa565b610255565b6040516100be91906113f1565b60405180910390f35b6100e160048036038101906100dc91906114a4565b61027b565b6040516100ee91906113f1565b60405180910390f35b610111600480360381019061010c919061155a565b6103ab565b005b61012d600480360381019061012891906115db565b61055a565b60405161013a91906113f1565b60405180910390f35b61015d600480360381019061015891906112fa565b610632565b60405161016a91906113f1565b60405180910390f35b60007f59d1d43c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061023e57507f691f3431000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061024e575061024d82610658565b5b9050919050565b60608260018151811061026b5761026a611608565b5b6020026020010151905092915050565b60606103a463de9abe5e60e01b6040518060200160405280600081525061039586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061038789610379600061036b600261035d8f61034f60046103417f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610ad290919063ffffffff16565b610b349092919063ffffffff16565b9392505050565b600084848101906103bc9190611637565b905060008060008060008088888101906103d691906117f1565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016104239493929190611b00565b600060405180830381865afa158015610440573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906104699190611c7f565b905084518151146104b557805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016104ac929190611ce1565b60405180910390fd5b60006105508483856040516024016104ce929190611d0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff16610cbf90919063ffffffff16565b9050805160208201f35b606061062d632682dd6660e01b6040518060200160405280600081525061061e85610610600061060260036105f48b6105e660046105d87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006106c2565b6107d190919063ffffffff16565b6108b290919063ffffffff16565b61093390919063ffffffff16565b610a1490919063ffffffff16565b6108b290919063ffffffff16565b610b349092919063ffffffff16565b919050565b60608260018151811061064857610647611608565b5b6020026020010151905092915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6106ca610fa4565b6000602067ffffffffffffffff8111156106e7576106e66110e4565b5b6040519080825280602002602001820160405280156107155781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610735576107346110e4565b5b60405190808252806020026020018201604052801561076857816020015b60608152602001906001900390816107535790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b6107d9610fa4565b6000836040015190506000815190506000811180156107fc575060208560600151105b1561080d5761080c8560ff610d0b565b5b6001810182526020856040015151111561085f5760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016108569190611d41565b60405180910390fd5b6000856060018181525050610875856000610d0b565b6108a7856108a2878760405160200161088e9190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b6108ba610fa4565b60208360600151106108f8576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61092a8361092585856040516020016109119190611d6b565b604051602081830303815290604052610db2565b610d0b565b82905092915050565b61093b610fa4565b60008360400151905060008151905060008111801561095e575060208560600151105b1561096f5761096e8560ff610d0b565b5b600181018252602085604001515111156109c15760206040517f128e70080000000000000000000000000000000000000000000000000000000081526004016109b89190611d41565b60405180910390fd5b60008560600181815250506109d7856001610d0b565b610a0985610a0487876040516020016109f09190611d41565b604051602081830303815290604052610db2565b610d0b565b849250505092915050565b610a1c610fa4565b6020836060015110610a5a576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610a735750601f8260ff16115b15610abc57818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610ab3929190611dce565b60405180910390fd5b610ac98383602017610d0b565b82905092915050565b610ada610fa4565b6020836060015110610b18576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2b83610b268585610db2565b610d0b565b82905092915050565b6000836040015151118015610b4d575060208360600151105b15610b5e57610b5d8360ff610d0b565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bae573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bd79190611f79565b846020015185604001518660800151604051602401610bf893929190611fc2565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b86600001518760200151886040015189608001518989604051602001610c709695949392919061206b565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401610cb69594939291906121ed565b60405180910390fd5b6060610d03838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610def565b905092915050565b60006001836040015151610d1f9190612284565b9050826060018051809190610d33906122b8565b8152506008610d429190612300565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c83604001518281518110610d8157610d80611608565b5b60200260200101511783604001518281518110610da157610da0611608565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff1681518110610ddd57610ddc611608565b5b60200260200101819052505092915050565b606082471015610e34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2b906123b4565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610e5d9190612410565b60006040518083038185875af1925050503d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b5091509150610eb087838387610ebc565b92505050949350505050565b60608315610f1e576000835103610f1657610ed685610f31565b610f15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0c90612473565b60405180910390fd5b5b829050610f29565b610f288383610f54565b5b949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600082511115610f675781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b91906113f1565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61104881611013565b811461105357600080fd5b50565b6000813590506110658161103f565b92915050565b60006020828403121561108157611080611009565b5b600061108f84828501611056565b91505092915050565b60008115159050919050565b6110ad81611098565b82525050565b60006020820190506110c860008301846110a4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61111c826110d3565b810181811067ffffffffffffffff8211171561113b5761113a6110e4565b5b80604052505050565b600061114e610fff565b905061115a8282611113565b919050565b600067ffffffffffffffff82111561117a576111796110e4565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111b0576111af6110e4565b5b6111b9826110d3565b9050602081019050919050565b82818337600083830152505050565b60006111e86111e384611195565b611144565b90508281526020810184848401111561120457611203611190565b5b61120f8482856111c6565b509392505050565b600082601f83011261122c5761122b6110ce565b5b813561123c8482602086016111d5565b91505092915050565b60006112586112538461115f565b611144565b9050808382526020820190506020840283018581111561127b5761127a61118b565b5b835b818110156112c257803567ffffffffffffffff8111156112a05761129f6110ce565b5b8086016112ad8982611217565b8552602085019450505060208101905061127d565b5050509392505050565b600082601f8301126112e1576112e06110ce565b5b81356112f1848260208601611245565b91505092915050565b6000806040838503121561131157611310611009565b5b600083013567ffffffffffffffff81111561132f5761132e61100e565b5b61133b858286016112cc565b925050602083013567ffffffffffffffff81111561135c5761135b61100e565b5b61136885828601611217565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b838110156113ac578082015181840152602081019050611391565b60008484015250505050565b60006113c382611372565b6113cd818561137d565b93506113dd81856020860161138e565b6113e6816110d3565b840191505092915050565b6000602082019050818103600083015261140b81846113b8565b905092915050565b6000819050919050565b61142681611413565b811461143157600080fd5b50565b6000813590506114438161141d565b92915050565b600080fd5b60008083601f840112611464576114636110ce565b5b8235905067ffffffffffffffff81111561148157611480611449565b5b60208301915083600182028301111561149d5761149c61118b565b5b9250929050565b6000806000604084860312156114bd576114bc611009565b5b60006114cb86828701611434565b935050602084013567ffffffffffffffff8111156114ec576114eb61100e565b5b6114f88682870161144e565b92509250509250925092565b60008083601f84011261151a576115196110ce565b5b8235905067ffffffffffffffff81111561153757611536611449565b5b6020830191508360018202830111156115535761155261118b565b5b9250929050565b6000806000806040858703121561157457611573611009565b5b600085013567ffffffffffffffff8111156115925761159161100e565b5b61159e87828801611504565b9450945050602085013567ffffffffffffffff8111156115c1576115c061100e565b5b6115cd87828801611504565b925092505092959194509250565b6000602082840312156115f1576115f0611009565b5b60006115ff84828501611434565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561164d5761164c611009565b5b600082013567ffffffffffffffff81111561166b5761166a61100e565b5b61167784828501611217565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006116ab82611680565b9050919050565b60006116bd826116a0565b9050919050565b6116cd816116b2565b81146116d857600080fd5b50565b6000813590506116ea816116c4565b92915050565b60006116fb82611680565b9050919050565b61170b816116f0565b811461171657600080fd5b50565b60008135905061172881611702565b92915050565b600067ffffffffffffffff821115611749576117486110e4565b5b602082029050602081019050919050565b600061176d6117688461172e565b611144565b905080838252602082019050602084028301858111156117905761178f61118b565b5b835b818110156117b957806117a58882611434565b845260208401935050602081019050611792565b5050509392505050565b600082601f8301126117d8576117d76110ce565b5b81356117e884826020860161175a565b91505092915050565b60008060008060008060c0878903121561180e5761180d611009565b5b600061181c89828a016116db565b965050602061182d89828a01611719565b955050604087013567ffffffffffffffff81111561184e5761184d61100e565b5b61185a89828a016117c3565b945050606087013567ffffffffffffffff81111561187b5761187a61100e565b5b61188789828a016112cc565b935050608061189889828a01611056565b92505060a087013567ffffffffffffffff8111156118b9576118b861100e565b5b6118c589828a01611217565b9150509295509295509295565b6118db816116a0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61191681611413565b82525050565b6000611928838361190d565b60208301905092915050565b6000602082019050919050565b600061194c826118e1565b61195681856118ec565b9350611961836118fd565b8060005b83811015611992578151611979888261191c565b975061198483611934565b925050600181019050611965565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006119f2826119cb565b6119fc81856119d6565b9350611a0c81856020860161138e565b611a15816110d3565b840191505092915050565b6000611a2c83836119e7565b905092915050565b6000602082019050919050565b6000611a4c8261199f565b611a5681856119aa565b935083602082028501611a68856119bb565b8060005b85811015611aa45784840389528151611a858582611a20565b9450611a9083611a34565b925060208a01995050600181019050611a6c565b50829750879550505050505092915050565b600082825260208201905092915050565b6000611ad2826119cb565b611adc8185611ab6565b9350611aec81856020860161138e565b611af5816110d3565b840191505092915050565b6000608082019050611b1560008301876118d2565b8181036020830152611b278186611941565b90508181036040830152611b3b8185611a41565b90508181036060830152611b4f8184611ac7565b905095945050505050565b6000611b6d611b6884611195565b611144565b905082815260208101848484011115611b8957611b88611190565b5b611b9484828561138e565b509392505050565b600082601f830112611bb157611bb06110ce565b5b8151611bc1848260208601611b5a565b91505092915050565b6000611bdd611bd88461115f565b611144565b90508083825260208201905060208402830185811115611c0057611bff61118b565b5b835b81811015611c4757805167ffffffffffffffff811115611c2557611c246110ce565b5b808601611c328982611b9c565b85526020850194505050602081019050611c02565b5050509392505050565b600082601f830112611c6657611c656110ce565b5b8151611c76848260208601611bca565b91505092915050565b600060208284031215611c9557611c94611009565b5b600082015167ffffffffffffffff811115611cb357611cb261100e565b5b611cbf84828501611c51565b91505092915050565b6000819050919050565b611cdb81611cc8565b82525050565b6000604082019050611cf66000830185611cd2565b611d036020830184611cd2565b9392505050565b60006040820190508181036000830152611d248185611a41565b90508181036020830152611d388184611ac7565b90509392505050565b6000602082019050611d566000830184611cd2565b92915050565b611d6581611413565b82525050565b6000602082019050611d806000830184611d5c565b92915050565b600060ff82169050919050565b6000819050919050565b6000611db8611db3611dae84611d86565b611d93565b611cc8565b9050919050565b611dc881611d9d565b82525050565b6000604082019050611de36000830185611dbf565b611df06020830184611cd2565b9392505050565b600067ffffffffffffffff821115611e1257611e116110e4565b5b602082029050602081019050919050565b600067ffffffffffffffff821115611e3e57611e3d6110e4565b5b611e47826110d3565b9050602081019050919050565b6000611e67611e6284611e23565b611144565b905082815260208101848484011115611e8357611e82611190565b5b611e8e84828561138e565b509392505050565b600082601f830112611eab57611eaa6110ce565b5b8151611ebb848260208601611e54565b91505092915050565b6000611ed7611ed284611df7565b611144565b90508083825260208201905060208402830185811115611efa57611ef961118b565b5b835b81811015611f4157805167ffffffffffffffff811115611f1f57611f1e6110ce565b5b808601611f2c8982611e96565b85526020850194505050602081019050611efc565b5050509392505050565b600082601f830112611f6057611f5f6110ce565b5b8151611f70848260208601611ec4565b91505092915050565b600060208284031215611f8f57611f8e611009565b5b600082015167ffffffffffffffff811115611fad57611fac61100e565b5b611fb984828501611f4b565b91505092915050565b6000606082019050611fd760008301866118d2565b8181036020830152611fe98185611941565b90508181036040830152611ffd8184611a41565b9050949350505050565b600061202261201d61201884611680565b611d93565b611680565b9050919050565b600061203482612007565b9050919050565b600061204682612029565b9050919050565b6120568161203b565b82525050565b61206581611013565b82525050565b600060c082019050612080600083018961204d565b61208d60208301886118d2565b818103604083015261209f8187611941565b905081810360608301526120b38186611a41565b90506120c2608083018561205c565b81810360a08301526120d48184611ac7565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061212982611372565b612133818561210d565b935061214381856020860161138e565b61214c816110d3565b840191505092915050565b6000612163838361211e565b905092915050565b6000602082019050919050565b6000612183826120e1565b61218d81856120ec565b93508360208202850161219f856120fd565b8060005b858110156121db57848403895281516121bc8582612157565b94506121c78361216b565b925060208a019950506001810190506121a3565b50829750879550505050505092915050565b600060a08201905061220260008301886118d2565b81810360208301526122148187612178565b905081810360408301526122288186611ac7565b9050612237606083018561205c565b81810360808301526122498184611ac7565b90509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061228f82611cc8565b915061229a83611cc8565b92508282039050818111156122b2576122b1612255565b5b92915050565b60006122c382611cc8565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122f5576122f4612255565b5b600182019050919050565b600061230b82611cc8565b915061231683611cc8565b925082820261232481611cc8565b9150828204841483151761233b5761233a612255565b5b5092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061239e60268361137d565b91506123a982612342565b604082019050919050565b600060208201905081810360008301526123cd81612391565b9050919050565b600081905092915050565b60006123ea826119cb565b6123f481856123d4565b935061240481856020860161138e565b80840191505092915050565b600061241c82846123df565b915081905092915050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b600061245d601d8361137d565b915061246882612427565b602082019050919050565b6000602082019050818103600083015261248c81612450565b905091905056fea2646970667358221220afaaec86b0c7316f6c3a4bf521d82e9308f1718ef909e9b50d9b1eb48dc0b1f064736f6c63430008130033", + "numDeployments": 5, + "solcInputHash": "7cc7da1092d13c01f4d5f27229751af2", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEVMVerifier\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"contract IDefaultReverseResolver\",\"name\":\"_defaultReverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommandTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"InvalidReference\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"}],\"name\":\"ResponseLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"max\",\"type\":\"uint256\"}],\"name\":\"TooManyCommands\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extradata\",\"type\":\"bytes\"}],\"name\":\"getStorageSlotsCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"nameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"callbackdata\",\"type\":\"bytes\"}],\"name\":\"textCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getStorageSlotsCallback(bytes,bytes)\":{\"details\":\"Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\"},\"resolve(bytes,bytes)\":{\"details\":\"Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\",\"params\":{\"data\":\"The actual calldata\",\"name\":\"DNS encoded ENS name to query\"},\"returns\":{\"result\":\"result of the call\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L1ReverseResolver.sol\":\"L1ReverseResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /**\\n * Returns the name associated with an ENS node, for reverse records.\\n * Defined in EIP181.\\n * @param node The ENS node to query.\\n * @return The associated name.\\n */\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x9ec392b612447b1acbdc01114f2da2837a658d3f3157f60a99c5269f0b623346\",\"license\":\"MIT\"},\"@ensdomains/ens-contracts/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\"},\"@ensdomains/ens-contracts/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 r, bool valid) {\\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 r := or(shl(8, r), 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\",\"keccak256\":\"0xcae20ad72181f47dfe7fba7d88e8d902a01576b16e93362878e726989d6cfb4d\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\n/**\\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\\n * inherit from this contract in order to handle callbacks correctly.\\n */\\nabstract contract EVMFetchTarget {\\n using Address for address;\\n\\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\\n\\n /**\\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\\n */\\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\\n bytes memory proof = abi.decode(response, (bytes));\\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\\n if(values.length != commands.length) {\\n revert ResponseLengthMismatch(values.length, commands.length);\\n }\\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\\n assembly {\\n return(add(ret, 32), mload(ret))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4653f974a897ce78b7bc3779ba0bb7767df99add49de4f0e9089399f47bb5942\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/EVMFetcher.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IEVMVerifier } from './IEVMVerifier.sol';\\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\\n\\ninterface IEVMGateway {\\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\\n}\\n\\nuint8 constant FLAG_DYNAMIC = 0x01;\\nuint8 constant OP_CONSTANT = 0x00;\\nuint8 constant OP_BACKREF = 0x20;\\nuint8 constant OP_END = 0xff;\\n\\n/**\\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\\n * See l1-verifier/test/TestL1.sol for example usage.\\n */\\nlibrary EVMFetcher {\\n uint256 constant MAX_COMMANDS = 32;\\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\\n\\n using Address for address;\\n\\n error TooManyCommands(uint256 max);\\n error CommandTooLong();\\n error InvalidReference(uint256 value, uint256 max);\\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\\n\\n struct EVMFetchRequest {\\n IEVMVerifier verifier;\\n address target;\\n bytes32[] commands;\\n uint256 operationIdx;\\n bytes[] constants;\\n }\\n\\n /**\\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\\n * another chain.\\n * Supports dynamic length values and slot numbers derived from other retrieved values.\\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\\n * @param target The address of the contract to fetch storage proofs for.\\n */\\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\\n assembly {\\n mstore(commands, 0) // Set current array length to 0\\n mstore(constants, 0)\\n } \\n return EVMFetchRequest(verifier, target, commands, 0, constants);\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, 0);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Starts describing a new fetch request.\\n * Paths specify a series of hashing operations to derive the final slot ID.\\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\\n * lays out storage variables.\\n * @param request The request object being operated on.\\n * @param baseSlot The base slot ID that forms the root of the path.\\n */\\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\\n bytes32[] memory commands = request.commands;\\n uint256 commandIdx = commands.length;\\n if(commandIdx > 0 && request.operationIdx < 32) {\\n // Terminate previous command\\n _addOperation(request, OP_END);\\n }\\n assembly {\\n mstore(commands, add(commandIdx, 1)) // Increment command array length\\n }\\n if(request.commands.length > MAX_COMMANDS) {\\n revert TooManyCommands(MAX_COMMANDS);\\n }\\n request.operationIdx = 0;\\n _addOperation(request, FLAG_DYNAMIC);\\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `uint256` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes32` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds an `address` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, abi.encode(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `bytes` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, el));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a `string` element to the current path.\\n * @param request The request object being operated on.\\n * @param el The element to add.\\n */\\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n _addOperation(request, _addConstant(request, bytes(el)));\\n return request;\\n }\\n\\n /**\\n * @dev Adds a reference to a previous fetch to the current path.\\n * @param request The request object being operated on.\\n * @param idx The index of the previous fetch request, starting at 0.\\n */\\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\\n if(request.operationIdx >= 32) {\\n revert CommandTooLong();\\n }\\n if(idx > request.commands.length || idx > 31) {\\n revert InvalidReference(idx, request.commands.length);\\n }\\n _addOperation(request, OP_BACKREF | idx);\\n return request;\\n }\\n\\n /**\\n * @dev Initiates the fetch request.\\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\\n * `callback` with the results of the operation.\\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\\n * @param callbackData Extra data to supply to the callback.\\n */\\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\\n if(request.commands.length > 0 && request.operationIdx < 32) {\\n // Terminate last command\\n _addOperation(request, OP_END);\\n }\\n revert OffchainLookup(\\n address(this),\\n request.verifier.gatewayURLs(),\\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\\n EVMFetchTarget.getStorageSlotsCallback.selector,\\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\\n );\\n }\\n\\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\\n bytes[] memory constants = request.constants;\\n idx = uint8(constants.length);\\n assembly {\\n mstore(constants, add(idx, 1)) // Increment constant array length\\n }\\n constants[idx] = value;\\n }\\n\\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\\n uint256 commandIdx = request.commands.length - 1;\\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\\n }\\n}\\n\",\"keccak256\":\"0x5a6a955ebf3e6da9ce8d39e2729c35e4e800426025954a9a9777c209447ff8b4\",\"license\":\"MIT\"},\"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\ninterface IEVMVerifier {\\n function gatewayURLs() external view returns(string[] memory);\\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\\n}\\n\",\"keccak256\":\"0x30a635309aeebbde83774010eea5e975b8e73d1932140457121eefdce7792d72\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\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, it is bubbled up by this\\n * function (like regular Solidity function calls).\\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 * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\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 * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"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\"},\"contracts/IDefaultReverseResolver.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IDefaultReverseResolver {\\n function name(address addr) external view returns (string memory);\\n\\n function text(\\n address addr,\\n string memory key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x0233c067351640bcfff8824150323e34f06abf239def880164a10eb8846479cf\"},\"contracts/L1ReverseResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\\\";\\nimport \\\"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport \\\"./IDefaultReverseResolver.sol\\\";\\n\\ncontract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 {\\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\\n IEVMVerifier immutable verifier;\\n address immutable target;\\n IDefaultReverseResolver immutable defaultReverseResolver;\\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\\n uint256 constant RECORD_VERSIONS_SLOT = 4;\\n uint256 constant ADDRESS_LENGTH = 40;\\n using HexUtils for bytes;\\n\\n constructor(IEVMVerifier _verifier, address _target, IDefaultReverseResolver _defaultReverseResolver ) {\\n verifier = _verifier;\\n target = _target;\\n defaultReverseResolver = _defaultReverseResolver;\\n }\\n\\n /** \\n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\\n * @param name DNS encoded ENS name to query\\n * @param data The actual calldata\\n * @return result result of the call\\n */\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) {\\n bytes4 selector = bytes4(data);\\n (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1);\\n if (selector == INameResolver.name.selector) {\\n (bytes32 node) = abi.decode(data[4:], (bytes32));\\n return bytes(_name(node, addr));\\n }\\n if (selector == ITextResolver.text.selector) {\\n (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string));\\n return bytes(_text(node, key, addr));\\n }\\n }\\n\\n function _name(bytes32 node, address addr) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_NAME_SLOT)\\n .ref(0)\\n .element(node)\\n .fetch(this.nameCallback.selector, abi.encode(addr));\\n }\\n\\n function nameCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) { \\n if(values[1].length == 0 ){\\n (address addr) = abi.decode(callbackdata, (address));\\n return defaultReverseResolver.name(addr);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function _text(\\n bytes32 node,\\n string memory key,\\n address addr\\n ) private view returns (string memory) {\\n EVMFetcher.newFetchRequest(verifier, target)\\n .getStatic(RECORD_VERSIONS_SLOT)\\n .element(node)\\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\\n .ref(0)\\n .element(node)\\n .element(key)\\n .fetch(this.textCallback.selector, abi.encode(addr, key));\\n }\\n\\n function textCallback(\\n bytes[] memory values,\\n bytes memory callbackdata\\n ) public view returns (string memory) {\\n if(values[1].length == 0 ){\\n (address addr, string memory key) = abi.decode(callbackdata, (address, string));\\n return defaultReverseResolver.text(addr, key);\\n }else{\\n return string(values[1]);\\n }\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public override view returns (bool) {\\n return\\n interfaceId == type(IExtendedResolver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0xb09771bfaf5dd9a01da9efecfbc15abc43a85501d9264c23895bbbf6edf8637a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002d5838038062002d588339818101604052810190620000379190620001d0565b8273ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250505050506200022c565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200010e82620000e1565b9050919050565b6000620001228262000101565b9050919050565b620001348162000115565b81146200014057600080fd5b50565b600081519050620001548162000129565b92915050565b620001658162000101565b81146200017157600080fd5b50565b60008151905062000185816200015a565b92915050565b6000620001988262000101565b9050919050565b620001aa816200018b565b8114620001b657600080fd5b50565b600081519050620001ca816200019f565b92915050565b600080600060608486031215620001ec57620001eb620000dc565b5b6000620001fc8682870162000143565b93505060206200020f8682870162000174565b92505060406200022286828701620001b9565b9150509250925092565b60805160a05160c051612ae762000271600039600081816101f2015261063a015260008181610870015261095f01526000818161084f015261093e0152612ae76000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c5780632682dd661461008c5780635bdaa916146100bc5780639061b923146100d8578063de9abe5e14610108575b600080fd5b6100766004803603810190610071919061142f565b610138565b6040516100839190611477565b60405180910390f35b6100a660048036038101906100a191906116be565b6101b2565b6040516100b391906117b5565b60405180910390f35b6100d660048036038101906100d19190611832565b6102bc565b005b6100f260048036038101906100ed9190611832565b61046b565b6040516100ff9190611908565b60405180910390f35b610122600480360381019061011d91906116be565b6105f7565b60405161012f91906117b5565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101ab57506101aa82610707565b5b9050919050565b60606000836001815181106101ca576101c961192a565b5b60200260200101515103610297576000828060200190518101906101ee91906119b7565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166301984892826040518263ffffffff1660e01b81526004016102499190611a05565b600060405180830381865afa158015610266573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061028f9190611ac1565b9150506102b6565b826001815181106102ab576102aa61192a565b5b602002602001015190505b92915050565b600084848101906102cd9190611b0a565b905060008060008060008088888101906102e79190611c9f565b95509550955095509550955060008673ffffffffffffffffffffffffffffffffffffffff16633baa6d508787878c6040518563ffffffff1660e01b81526004016103349493929190611f4a565b600060405180830381865afa158015610351573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061037a91906120c9565b905084518151146103c657805185516040517f291894250000000000000000000000000000000000000000000000000000000081526004016103bd92919061212b565b60405180910390fd5b60006104618483856040516024016103df929190612154565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050503073ffffffffffffffffffffffffffffffffffffffff1661077190919063ffffffff16565b9050805160208201f35b6060600083839061047c91906121a3565b905060006104dc87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505060018060286104d79190612231565b6107bd565b50905063691f343160e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191603610563576000858560049080926105409392919061226f565b81019061054d91906122aa565b90506105598183610806565b93505050506105ef565b6359d1d43c60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036105ec57600080868660049080926105c59392919061226f565b8101906105d29190612347565b915091506105e18282856108ef565b9450505050506105ef565b50505b949350505050565b606060008360018151811061060f5761060e61192a565b5b602002602001015151036106e2576000808380602001905181019061063491906123a3565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d977f6b583836040518363ffffffff1660e01b81526004016106939291906123ff565b600060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906106d99190611ac1565b92505050610701565b826001815181106106f6576106f561192a565b5b602002602001015190505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60606107b5838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506109ed565b905092915050565b600080602884846107ce919061242f565b10156107e057600080915091506107fe565b6000806107ee878787610aba565b915091508160001c819350935050505b935093915050565b60606108e9632682dd6660e01b836040516020016108249190611a05565b6040516020818303038152906040526108da866108cc60006108be60036108b08c6108a260046108947f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b610faf9092919063ffffffff16565b92915050565b60606109e663de9abe5e60e01b838560405160200161090f9291906123ff565b6040516020818303038152906040526109d7866109c9896109bb60006109ad600261099f8f61099160046109837f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610b9f565b610cae90919063ffffffff16565b610d8f90919063ffffffff16565b610e1090919063ffffffff16565b610ef190919063ffffffff16565b610d8f90919063ffffffff16565b61113a90919063ffffffff16565b610faf9092919063ffffffff16565b9392505050565b606082471015610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124d5565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610a5b9190612531565b60006040518083038185875af1925050503d8060008114610a98576040519150601f19603f3d011682016040523d82523d6000602084013e610a9d565b606091505b5091509150610aae8783838761119c565b92505050949350505050565b600080600190508451831115610acf57600080fd5b610b31565b6000603a8210602f83111615610aef57603082039050610b2c565b60478210604083111615610b0b57600a60418303019050610b2c565b60678210606083111615610b2757600a60618303019050610b2c565b60ff90505b919050565b60208501845b84811015610b9557610b4e8183015160001a610ad4565b610b606001830184015160001a610ad4565b60ff811460ff83141715610b7957600094505050610b95565b808260041b17808760081b179650505050600281019050610b37565b5050935093915050565b610ba7611368565b6000602067ffffffffffffffff811115610bc457610bc36114a8565b5b604051908082528060200260200182016040528015610bf25781602001602082028036833780820191505090505b5090506000602067ffffffffffffffff811115610c1257610c116114a8565b5b604051908082528060200260200182016040528015610c4557816020015b6060815260200190600190039081610c305790505b50905060008252600081526040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160008152602001828152509250505092915050565b610cb6611368565b600083604001519050600081519050600081118015610cd9575060208560600151105b15610cea57610ce98560ff611211565b5b60018101825260208560400151511115610d3c5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610d339190612548565b60405180910390fd5b6000856060018181525050610d52856000611211565b610d8485610d7f8787604051602001610d6b9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610d97611368565b6020836060015110610dd5576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0783610e028585604051602001610dee9190612572565b6040516020818303038152906040526112b8565b611211565b82905092915050565b610e18611368565b600083604001519050600081519050600081118015610e3b575060208560600151105b15610e4c57610e4b8560ff611211565b5b60018101825260208560400151511115610e9e5760206040517f128e7008000000000000000000000000000000000000000000000000000000008152600401610e959190612548565b60405180910390fd5b6000856060018181525050610eb4856001611211565b610ee685610ee18787604051602001610ecd9190612548565b6040516020818303038152906040526112b8565b611211565b849250505092915050565b610ef9611368565b6020836060015110610f37576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260400151518260ff161180610f505750601f8260ff16115b15610f9957818360400151516040517f101586e0000000000000000000000000000000000000000000000000000000008152600401610f909291906125d5565b60405180910390fd5b610fa68383602017611211565b82905092915050565b6000836040015151118015610fc8575060208360600151105b15610fd957610fd88360ff611211565b5b30836000015173ffffffffffffffffffffffffffffffffffffffff1663b50f2fbc6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611029573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061105291906126df565b84602001518560400151866080015160405160240161107393929190612728565b60405160208183030381529060405263ea9cd3bf60e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050635bdaa91660e01b866000015187602001518860400151896080015189896040516020016110eb969594939291906127d1565b6040516020818303038152906040526040517f556f1830000000000000000000000000000000000000000000000000000000008152600401611131959493929190612953565b60405180910390fd5b611142611368565b6020836060015110611180576040517fb00fd63800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111938361118e85856112b8565b611211565b82905092915050565b606083156111fe5760008351036111f6576111b6856112f5565b6111f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ec90612a07565b60405180910390fd5b5b829050611209565b6112088383611318565b5b949350505050565b60006001836040015151611225919061242f565b905082606001805180919061123990612a27565b81525060086112489190612a6f565b8260f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c836040015182815181106112875761128661192a565b5b602002602001015117836040015182815181106112a7576112a661192a565b5b602002602001018181525050505050565b600080836080015190508051915060018201815282818360ff16815181106112e3576112e261192a565b5b60200260200101819052505092915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008251111561132b5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135f91906117b5565b60405180910390fd5b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016060815260200160008152602001606081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61140c816113d7565b811461141757600080fd5b50565b60008135905061142981611403565b92915050565b600060208284031215611445576114446113cd565b5b60006114538482850161141a565b91505092915050565b60008115159050919050565b6114718161145c565b82525050565b600060208201905061148c6000830184611468565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114e082611497565b810181811067ffffffffffffffff821117156114ff576114fe6114a8565b5b80604052505050565b60006115126113c3565b905061151e82826114d7565b919050565b600067ffffffffffffffff82111561153e5761153d6114a8565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611574576115736114a8565b5b61157d82611497565b9050602081019050919050565b82818337600083830152505050565b60006115ac6115a784611559565b611508565b9050828152602081018484840111156115c8576115c7611554565b5b6115d384828561158a565b509392505050565b600082601f8301126115f0576115ef611492565b5b8135611600848260208601611599565b91505092915050565b600061161c61161784611523565b611508565b9050808382526020820190506020840283018581111561163f5761163e61154f565b5b835b8181101561168657803567ffffffffffffffff81111561166457611663611492565b5b80860161167189826115db565b85526020850194505050602081019050611641565b5050509392505050565b600082601f8301126116a5576116a4611492565b5b81356116b5848260208601611609565b91505092915050565b600080604083850312156116d5576116d46113cd565b5b600083013567ffffffffffffffff8111156116f3576116f26113d2565b5b6116ff85828601611690565b925050602083013567ffffffffffffffff8111156117205761171f6113d2565b5b61172c858286016115db565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611770578082015181840152602081019050611755565b60008484015250505050565b600061178782611736565b6117918185611741565b93506117a1818560208601611752565b6117aa81611497565b840191505092915050565b600060208201905081810360008301526117cf818461177c565b905092915050565b600080fd5b60008083601f8401126117f2576117f1611492565b5b8235905067ffffffffffffffff81111561180f5761180e6117d7565b5b60208301915083600182028301111561182b5761182a61154f565b5b9250929050565b6000806000806040858703121561184c5761184b6113cd565b5b600085013567ffffffffffffffff81111561186a576118696113d2565b5b611876878288016117dc565b9450945050602085013567ffffffffffffffff811115611899576118986113d2565b5b6118a5878288016117dc565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006118da826118b3565b6118e481856118be565b93506118f4818560208601611752565b6118fd81611497565b840191505092915050565b6000602082019050818103600083015261192281846118cf565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061198482611959565b9050919050565b61199481611979565b811461199f57600080fd5b50565b6000815190506119b18161198b565b92915050565b6000602082840312156119cd576119cc6113cd565b5b60006119db848285016119a2565b91505092915050565b60006119ef82611959565b9050919050565b6119ff816119e4565b82525050565b6000602082019050611a1a60008301846119f6565b92915050565b600067ffffffffffffffff821115611a3b57611a3a6114a8565b5b611a4482611497565b9050602081019050919050565b6000611a64611a5f84611a20565b611508565b905082815260208101848484011115611a8057611a7f611554565b5b611a8b848285611752565b509392505050565b600082601f830112611aa857611aa7611492565b5b8151611ab8848260208601611a51565b91505092915050565b600060208284031215611ad757611ad66113cd565b5b600082015167ffffffffffffffff811115611af557611af46113d2565b5b611b0184828501611a93565b91505092915050565b600060208284031215611b2057611b1f6113cd565b5b600082013567ffffffffffffffff811115611b3e57611b3d6113d2565b5b611b4a848285016115db565b91505092915050565b6000611b5e826119e4565b9050919050565b611b6e81611b53565b8114611b7957600080fd5b50565b600081359050611b8b81611b65565b92915050565b600081359050611ba08161198b565b92915050565b600067ffffffffffffffff821115611bc157611bc06114a8565b5b602082029050602081019050919050565b6000819050919050565b611be581611bd2565b8114611bf057600080fd5b50565b600081359050611c0281611bdc565b92915050565b6000611c1b611c1684611ba6565b611508565b90508083825260208201905060208402830185811115611c3e57611c3d61154f565b5b835b81811015611c675780611c538882611bf3565b845260208401935050602081019050611c40565b5050509392505050565b600082601f830112611c8657611c85611492565b5b8135611c96848260208601611c08565b91505092915050565b60008060008060008060c08789031215611cbc57611cbb6113cd565b5b6000611cca89828a01611b7c565b9650506020611cdb89828a01611b91565b955050604087013567ffffffffffffffff811115611cfc57611cfb6113d2565b5b611d0889828a01611c71565b945050606087013567ffffffffffffffff811115611d2957611d286113d2565b5b611d3589828a01611690565b9350506080611d4689828a0161141a565b92505060a087013567ffffffffffffffff811115611d6757611d666113d2565b5b611d7389828a016115db565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611db581611bd2565b82525050565b6000611dc78383611dac565b60208301905092915050565b6000602082019050919050565b6000611deb82611d80565b611df58185611d8b565b9350611e0083611d9c565b8060005b83811015611e31578151611e188882611dbb565b9750611e2383611dd3565b925050600181019050611e04565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611e86826118b3565b611e908185611e6a565b9350611ea0818560208601611752565b611ea981611497565b840191505092915050565b6000611ec08383611e7b565b905092915050565b6000602082019050919050565b6000611ee082611e3e565b611eea8185611e49565b935083602082028501611efc85611e5a565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b6000608082019050611f5f60008301876119f6565b8181036020830152611f718186611de0565b90508181036040830152611f858185611ed5565b90508181036060830152611f9981846118cf565b905095945050505050565b6000611fb7611fb284611559565b611508565b905082815260208101848484011115611fd357611fd2611554565b5b611fde848285611752565b509392505050565b600082601f830112611ffb57611ffa611492565b5b815161200b848260208601611fa4565b91505092915050565b600061202761202284611523565b611508565b9050808382526020820190506020840283018581111561204a5761204961154f565b5b835b8181101561209157805167ffffffffffffffff81111561206f5761206e611492565b5b80860161207c8982611fe6565b8552602085019450505060208101905061204c565b5050509392505050565b600082601f8301126120b0576120af611492565b5b81516120c0848260208601612014565b91505092915050565b6000602082840312156120df576120de6113cd565b5b600082015167ffffffffffffffff8111156120fd576120fc6113d2565b5b6121098482850161209b565b91505092915050565b6000819050919050565b61212581612112565b82525050565b6000604082019050612140600083018561211c565b61214d602083018461211c565b9392505050565b6000604082019050818103600083015261216e8185611ed5565b9050818103602083015261218281846118cf565b90509392505050565b600082905092915050565b600082821b905092915050565b60006121af838361218b565b826121ba81356113d7565b925060048210156121fa576121f57fffffffff0000000000000000000000000000000000000000000000000000000083600403600802612196565b831692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061223c82612112565b915061224783612112565b925082820190508082111561225f5761225e612202565b5b92915050565b600080fd5b600080fd5b6000808585111561228357612282612265565b5b838611156122945761229361226a565b5b6001850283019150848603905094509492505050565b6000602082840312156122c0576122bf6113cd565b5b60006122ce84828501611bf3565b91505092915050565b60006122ea6122e584611a20565b611508565b90508281526020810184848401111561230657612305611554565b5b61231184828561158a565b509392505050565b600082601f83011261232e5761232d611492565b5b813561233e8482602086016122d7565b91505092915050565b6000806040838503121561235e5761235d6113cd565b5b600061236c85828601611bf3565b925050602083013567ffffffffffffffff81111561238d5761238c6113d2565b5b61239985828601612319565b9150509250929050565b600080604083850312156123ba576123b96113cd565b5b60006123c8858286016119a2565b925050602083015167ffffffffffffffff8111156123e9576123e86113d2565b5b6123f585828601611a93565b9150509250929050565b600060408201905061241460008301856119f6565b8181036020830152612426818461177c565b90509392505050565b600061243a82612112565b915061244583612112565b925082820390508181111561245d5761245c612202565b5b92915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b60006124bf602683611741565b91506124ca82612463565b604082019050919050565b600060208201905081810360008301526124ee816124b2565b9050919050565b600081905092915050565b600061250b826118b3565b61251581856124f5565b9350612525818560208601611752565b80840191505092915050565b600061253d8284612500565b915081905092915050565b600060208201905061255d600083018461211c565b92915050565b61256c81611bd2565b82525050565b60006020820190506125876000830184612563565b92915050565b600060ff82169050919050565b6000819050919050565b60006125bf6125ba6125b58461258d565b61259a565b612112565b9050919050565b6125cf816125a4565b82525050565b60006040820190506125ea60008301856125c6565b6125f7602083018461211c565b9392505050565b600067ffffffffffffffff821115612619576126186114a8565b5b602082029050602081019050919050565b600061263d612638846125fe565b611508565b905080838252602082019050602084028301858111156126605761265f61154f565b5b835b818110156126a757805167ffffffffffffffff81111561268557612684611492565b5b8086016126928982611a93565b85526020850194505050602081019050612662565b5050509392505050565b600082601f8301126126c6576126c5611492565b5b81516126d684826020860161262a565b91505092915050565b6000602082840312156126f5576126f46113cd565b5b600082015167ffffffffffffffff811115612713576127126113d2565b5b61271f848285016126b1565b91505092915050565b600060608201905061273d60008301866119f6565b818103602083015261274f8185611de0565b905081810360408301526127638184611ed5565b9050949350505050565b600061278861278361277e84611959565b61259a565b611959565b9050919050565b600061279a8261276d565b9050919050565b60006127ac8261278f565b9050919050565b6127bc816127a1565b82525050565b6127cb816113d7565b82525050565b600060c0820190506127e660008301896127b3565b6127f360208301886119f6565b81810360408301526128058187611de0565b905081810360608301526128198186611ed5565b905061282860808301856127c2565b81810360a083015261283a81846118cf565b9050979650505050505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b600061288f82611736565b6128998185612873565b93506128a9818560208601611752565b6128b281611497565b840191505092915050565b60006128c98383612884565b905092915050565b6000602082019050919050565b60006128e982612847565b6128f38185612852565b93508360208202850161290585612863565b8060005b85811015612941578484038952815161292285826128bd565b945061292d836128d1565b925060208a01995050600181019050612909565b50829750879550505050505092915050565b600060a08201905061296860008301886119f6565b818103602083015261297a81876128de565b9050818103604083015261298e81866118cf565b905061299d60608301856127c2565b81810360808301526129af81846118cf565b90509695505050505050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b60006129f1601d83611741565b91506129fc826129bb565b602082019050919050565b60006020820190508181036000830152612a20816129e4565b9050919050565b6000612a3282612112565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a6457612a63612202565b5b600182019050919050565b6000612a7a82612112565b9150612a8583612112565b9250828202612a9381612112565b91508282048414831517612aaa57612aa9612202565b5b509291505056fea264697066735822122030d2d39c55db05e43cc7652a743f9fc5c103fc49663b9a67ee668dfb221e9f0c64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": { "getStorageSlotsCallback(bytes,bytes)": { "details": "Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request." }, - "name(bytes32)": { + "resolve(bytes,bytes)": { + "details": "Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver", "params": { - "node": "The ENS node to query." + "data": "The actual calldata", + "name": "DNS encoded ENS name to query" }, "returns": { - "_0": "The associated name." + "result": "result of the call" } }, "supportsInterface(bytes4)": { "details": "See {IERC165-supportsInterface}." - }, - "text(bytes32,string)": { - "params": { - "key": "The text data key to query.", - "node": "The ENS node to query." - }, - "returns": { - "_0": "The associated text data." - } } }, "version": 1 }, "userdoc": { "kind": "user", - "methods": { - "name(bytes32)": { - "notice": "Returns the address associated with an ENS node." - }, - "text(bytes32,string)": { - "notice": "Returns the text data associated with an ENS node and key." - } - }, + "methods": {}, "version": 1 }, "storageLayout": { diff --git a/crosschain-reverse-resolver/deployments/sepolia/solcInputs/1051d0da171e6c4c0eb815a27588fee5.json b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/1051d0da171e6c4c0eb815a27588fee5.json new file mode 100644 index 00000000..ceac9ffe --- /dev/null +++ b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/1051d0da171e6c4c0eb815a27588fee5.json @@ -0,0 +1,135 @@ +{ + "language": "Solidity", + "sources": { + "@ensdomains/ens-contracts/contracts/registry/ENS.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n // Logged when the owner of a node assigns a new owner to a subnode.\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n // Logged when the owner of a node transfers ownership to a new account.\n event Transfer(bytes32 indexed node, address owner);\n\n // Logged when the resolver for a node changes.\n event NewResolver(bytes32 indexed node, address resolver);\n\n // Logged when the TTL of a node changes\n event NewTTL(bytes32 indexed node, uint64 ttl);\n\n // Logged when an operator is added or removed.\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n function setRecord(\n bytes32 node,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner\n ) external returns (bytes32);\n\n function setResolver(bytes32 node, address resolver) external;\n\n function setOwner(bytes32 node, address owner) external;\n\n function setTTL(bytes32 node, uint64 ttl) external;\n\n function setApprovalForAll(address operator, bool approved) external;\n\n function owner(bytes32 node) external view returns (address);\n\n function resolver(bytes32 node) external view returns (address);\n\n function ttl(bytes32 node) external view returns (uint64);\n\n function recordExists(bytes32 node) external view returns (bool);\n\n function isApprovedForAll(\n address owner,\n address operator\n ) external view returns (bool);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/IMulticallable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IMulticallable {\n function multicall(\n bytes[] calldata data\n ) external returns (bytes[] memory results);\n\n function multicallWithNodeCheck(\n bytes32,\n bytes[] calldata data\n ) external returns (bytes[] memory results);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/Multicallable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"./IMulticallable.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\nabstract contract Multicallable is IMulticallable, ERC165 {\n function _multicall(\n bytes32 nodehash,\n bytes[] calldata data\n ) internal returns (bytes[] memory results) {\n results = new bytes[](data.length);\n for (uint256 i = 0; i < data.length; i++) {\n if (nodehash != bytes32(0)) {\n bytes32 txNamehash = bytes32(data[i][4:36]);\n require(\n txNamehash == nodehash,\n \"multicall: All records must have a matching namehash\"\n );\n }\n (bool success, bytes memory result) = address(this).delegatecall(\n data[i]\n );\n require(success);\n results[i] = result;\n }\n return results;\n }\n\n // This function provides an extra security check when called\n // from priviledged contracts (such as EthRegistrarController)\n // that can set records on behalf of the node owners\n function multicallWithNodeCheck(\n bytes32 nodehash,\n bytes[] calldata data\n ) external returns (bytes[] memory results) {\n return _multicall(nodehash, data);\n }\n\n function multicall(\n bytes[] calldata data\n ) public override returns (bytes[] memory results) {\n return _multicall(bytes32(0), data);\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view virtual override returns (bool) {\n return\n interfaceID == type(IMulticallable).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface INameResolver {\n event NameChanged(bytes32 indexed node, string name);\n\n /**\n * Returns the name associated with an ENS node, for reverse records.\n * Defined in EIP181.\n * @param node The ENS node to query.\n * @return The associated name.\n */\n function name(bytes32 node) external view returns (string memory);\n}\n" + }, + "@ensdomains/ens-contracts/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" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IVersionableResolver {\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\n\n function recordVersions(bytes32 node) external view returns (uint64);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/IL2ReverseRegistrar.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface IL2ReverseRegistrar {\n function setName(string memory name) external returns (bytes32);\n\n function setNameForAddr(\n address addr,\n string memory name\n ) external returns (bytes32);\n\n function setNameForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function setText(\n string calldata key,\n string calldata value\n ) external returns (bytes32);\n\n function setTextForAddr(\n address addr,\n string calldata key,\n string calldata value\n ) external returns (bytes32);\n\n function setTextForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function clearRecords(address addr) external;\n\n function name(bytes32 node) external view returns (string memory);\n\n function text(\n bytes32 node,\n string calldata key\n ) external view returns (string memory);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/ISignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ISignatureReverseResolver {\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\n event ReverseClaimed(address indexed addr, bytes32 indexed node);\n event NameChanged(bytes32 indexed node, string name);\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key,\n string value\n );\n\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) external;\n\n function node(address addr) external view returns (bytes32);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./IL2ReverseRegistrar.sol\";\nimport \"./SignatureReverseResolver.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../resolvers/profiles/ITextResolver.sol\";\nimport \"../resolvers/profiles/INameResolver.sol\";\nimport \"../root/Controllable.sol\";\nimport \"../resolvers/Multicallable.sol\";\nimport \"../utils/LowLevelCallUtils.sol\";\n\nerror NotOwnerOfContract();\n\n/**\n * A L2 reverser registrar. Deployed to each L2 chain.\n * The contract will be verified on L1 Reverse Resolver under the namespace specified at constructor\n */\ncontract L2ReverseRegistrar is\n Multicallable,\n Ownable,\n IL2ReverseRegistrar,\n SignatureReverseResolver\n{\n using ECDSA for bytes32;\n\n bytes32 public immutable L2ReverseNode;\n\n /*\n * @dev Constructor\n * @param _L2ReverseNode The namespace to set. The converntion is '${cointype}.reverse'\n * @param _coinType The cointype converted from the chainId of the chain this contract is deployed to.\n */\n constructor(\n bytes32 _L2ReverseNode,\n uint256 _coinType\n ) SignatureReverseResolver(_L2ReverseNode, _coinType) {\n L2ReverseNode = _L2ReverseNode;\n }\n\n modifier ownerAndAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n address owner,\n uint256 inceptionDate,\n bytes memory signature\n ) {\n isOwnerAndAuthorisedWithSignature(\n hash,\n addr,\n owner,\n inceptionDate,\n signature\n );\n _;\n }\n\n function isAuthorised(address addr) internal view override returns (bool) {\n if (addr != msg.sender && !ownsContract(addr, msg.sender)) {\n revert Unauthorised();\n }\n }\n\n function isOwnerAndAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n address owner,\n uint256 inceptionDate,\n bytes memory signature\n ) internal view returns (bool) {\n bytes32 message = keccak256(\n abi.encodePacked(hash, addr, owner, inceptionDate, coinType)\n ).toEthSignedMessageHash();\n bytes32 node = _getNamehash(addr);\n\n if (!ownsContract(addr, owner)) {\n revert NotOwnerOfContract();\n }\n\n if (\n !SignatureChecker.isValidERC1271SignatureNow(\n owner,\n message,\n signature\n )\n ) {\n revert InvalidSignature();\n }\n\n if (\n inceptionDate <= lastUpdated[node] || // must be newer than current record\n inceptionDate / 1000 >= block.timestamp // must be in the past\n ) {\n revert SignatureOutOfDate();\n }\n }\n\n /**\n * @dev Sets the name for a contract that is owned by a SCW using a signature\n * @param contractAddr The reverse node to set\n * @param owner The owner of the contract (via Ownable)\n * @param name The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The signature of an address that will return true on isValidSignature for the owner\n * @return The ENS node hash of the reverse record.\n */\n function setNameForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n ownerAndAuthorisedWithSignature(\n keccak256(\n abi.encodePacked(\n IL2ReverseRegistrar\n .setNameForAddrWithSignatureAndOwnable\n .selector,\n name\n )\n ),\n contractAddr,\n owner,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(contractAddr);\n _setName(node, name, inceptionDate);\n emit NameChanged(node, name);\n emit ReverseClaimed(contractAddr, node);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the calling account.\n * @param name The name to set for this address.\n * @return The ENS node hash of the reverse record.\n */\n function setName(string memory name) public override returns (bytes32) {\n return setNameForAddr(msg.sender, name);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the addr provided account.\n * Can be used if the addr is a contract that is owned by a SCW.\n * @param name The name to set for this address.\n * @return The ENS node hash of the reverse record.\n */\n\n function setNameForAddr(\n address addr,\n string memory name\n ) public authorised(addr) returns (bytes32) {\n bytes32 node = _getNamehash(addr);\n _setName(node, name, block.timestamp);\n emit ReverseClaimed(addr, node);\n return node;\n }\n\n /**\n * @dev Sets the name for a contract that is owned by a SCW using a signature\n * @param contractAddr The reverse node to set\n * @param owner The owner of the contract (via Ownable)\n * @param key The name of the reverse record\n * @param value The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The signature of an address that will return true on isValidSignature for the owner\n * @return The ENS node hash of the reverse record.\n */\n function setTextForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n ownerAndAuthorisedWithSignature(\n keccak256(\n abi.encodePacked(\n IL2ReverseRegistrar\n .setTextForAddrWithSignatureAndOwnable\n .selector,\n key,\n value\n )\n ),\n contractAddr,\n owner,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(contractAddr);\n _setText(node, key, value, inceptionDate);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the calling account.\n * @param key The key for this text record.\n * @param value The value to set for this text record.\n * @return The ENS node hash of the reverse record.\n */\n function setText(\n string calldata key,\n string calldata value\n ) public override returns (bytes32) {\n return setTextForAddr(msg.sender, key, value);\n }\n\n /**\n * @dev Sets the `text(key)` record for the reverse ENS record associated with\n * the addr provided account.\n * @param key The key for this text record.\n * @param value The value to set for this text record.\n * @return The ENS node hash of the reverse record.\n */\n\n function setTextForAddr(\n address addr,\n string calldata key,\n string calldata value\n ) public override authorised(addr) returns (bytes32) {\n bytes32 node = _getNamehash(addr);\n _setText(node, key, value, block.timestamp);\n return node;\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 virtual override returns (string memory) {\n return _text(node, key);\n }\n\n /**\n * Returns the name associated with an ENS node, for reverse records.\n * Defined in EIP181.\n * @param node The ENS node to query.\n * @return The associated name.\n */\n function name(\n bytes32 node\n ) external view virtual override returns (string memory) {\n return _name(node);\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n */\n function clearRecords(address addr) public virtual authorised(addr) {\n _clearRecords(addr);\n }\n\n function ownsContract(\n address contractAddr,\n address addr\n ) internal view returns (bool) {\n try Ownable(contractAddr).owner() returns (address owner) {\n return owner == addr;\n } catch {\n return false;\n }\n }\n\n function supportsInterface(\n bytes4 interfaceID\n )\n public\n view\n override(Multicallable, SignatureReverseResolver)\n returns (bool)\n {\n return\n interfaceID == type(IL2ReverseRegistrar).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./ISignatureReverseResolver.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../root/Controllable.sol\";\nimport \"../utils/LowLevelCallUtils.sol\";\n\nerror InvalidSignature();\nerror SignatureOutOfDate();\nerror Unauthorised();\n\ncontract SignatureReverseResolver is Ownable, ISignatureReverseResolver {\n using ECDSA for bytes32;\n mapping(bytes32 => uint256) public lastUpdated;\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\n mapping(bytes32 => uint64) internal recordVersions;\n\n bytes32 public immutable ParentNode;\n uint256 public immutable coinType;\n\n /*\n * @dev Constructor\n * @param ParentNode The namespace to set.\n * @param _coinType The cointype converted from the chainId of the chain this contract is deployed to.\n */\n constructor(bytes32 _ParentNode, uint256 _coinType) {\n ParentNode = _ParentNode;\n coinType = _coinType;\n }\n\n modifier authorised(address addr) {\n isAuthorised(addr);\n _;\n }\n\n modifier authorisedSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) {\n isAuthorisedWithSignature(hash, addr, inceptionDate, signature);\n _;\n }\n\n function getLastUpdated(\n bytes32 node\n ) internal view virtual returns (uint256) {\n return lastUpdated[node];\n }\n\n function isAuthorised(address addr) internal view virtual returns (bool) {}\n\n function isAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) internal view returns (bool) {\n bytes32 message = keccak256(\n abi.encodePacked(hash, addr, inceptionDate, coinType)\n ).toEthSignedMessageHash();\n bytes32 node = _getNamehash(addr);\n\n if (!SignatureChecker.isValidSignatureNow(addr, message, signature)) {\n revert InvalidSignature();\n }\n\n if (\n inceptionDate <= lastUpdated[node] || // must be newer than current record\n inceptionDate / 1000 >= block.timestamp // must be in the past\n ) {\n revert SignatureOutOfDate();\n }\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param name The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setNameForAddrWithSignature\n .selector,\n name\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setName(node, name, inceptionDate);\n emit ReverseClaimed(addr, node);\n return node;\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param key The key of the text record\n * @param value The value of the text record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setTextForAddrWithSignature\n .selector,\n key,\n value\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setText(node, key, value, inceptionDate);\n return node;\n }\n\n function _setText(\n bytes32 node,\n string calldata key,\n string calldata value,\n uint256 inceptionDate\n ) internal {\n versionable_texts[recordVersions[node]][node][key] = value;\n _setLastUpdated(node, inceptionDate);\n emit TextChanged(node, key, key, 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 ) internal view returns (string memory) {\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n function _setName(\n bytes32 node,\n string memory newName,\n uint256 inceptionDate\n ) internal virtual {\n versionable_names[recordVersions[node]][node] = newName;\n _setLastUpdated(node, inceptionDate);\n emit NameChanged(node, newName);\n }\n\n function _name(bytes32 node) internal view returns (string memory) {\n return versionable_names[recordVersions[node]][node];\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n */\n function _clearRecords(address addr) internal {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n bytes32 reverseNode = keccak256(\n abi.encodePacked(ParentNode, labelHash)\n );\n recordVersions[reverseNode]++;\n emit VersionChanged(reverseNode, recordVersions[reverseNode]);\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n * @param signature A signature proving ownership of the node.\n */\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver.clearRecordsWithSignature.selector\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n {\n _clearRecords(addr);\n }\n\n /**\n * @dev Returns the node hash for a given account's reverse records.\n * @param addr The address to hash\n * @return The ENS node hash.\n */\n function node(address addr) public view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(\n ParentNode,\n LowLevelCallUtils.sha3HexAddress(addr)\n )\n );\n }\n\n function _getNamehash(address addr) internal view returns (bytes32) {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n return keccak256(abi.encodePacked(ParentNode, labelHash));\n }\n\n function _setLastUpdated(bytes32 node, uint256 inceptionDate) internal {\n lastUpdated[node] = inceptionDate;\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view virtual returns (bool) {\n return interfaceID == type(ISignatureReverseResolver).interfaceId;\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/root/Controllable.sol": { + "content": "pragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Controllable is Ownable {\n mapping(address => bool) public controllers;\n\n event ControllerChanged(address indexed controller, bool enabled);\n\n modifier onlyController() {\n require(\n controllers[msg.sender],\n \"Controllable: Caller is not a controller\"\n );\n _;\n }\n\n function setController(address controller, bool enabled) public onlyOwner {\n controllers[controller] = enabled;\n emit ControllerChanged(controller, enabled);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/utils/LowLevelCallUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.13;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nlibrary LowLevelCallUtils {\n // This is the hex encoding of the string 'abcdefghijklmnopqrstuvwxyz'\n // It is used as a constant to lookup the characters of the hex address\n bytes32 constant lookup =\n 0x3031323334353637383961626364656600000000000000000000000000000000;\n using Address for address;\n\n /**\n * @dev Makes a static call to the specified `target` with `data`. Return data can be fetched with\n * `returnDataSize` and `readReturnData`.\n * @param target The address to staticcall.\n * @param data The data to pass to the call.\n * @return success True if the call succeeded, or false if it reverts.\n */\n function functionStaticCall(\n address target,\n bytes memory data\n ) internal view returns (bool success) {\n require(\n target.isContract(),\n \"LowLevelCallUtils: static call to non-contract\"\n );\n assembly {\n success := staticcall(\n gas(),\n target,\n add(data, 32),\n mload(data),\n 0,\n 0\n )\n }\n }\n\n /**\n * @dev Returns the size of the return data of the most recent external call.\n */\n function returnDataSize() internal pure returns (uint256 len) {\n assembly {\n len := returndatasize()\n }\n }\n\n /**\n * @dev Reads return data from the most recent external call.\n * @param offset Offset into the return data.\n * @param length Number of bytes to return.\n */\n function readReturnData(\n uint256 offset,\n uint256 length\n ) internal pure returns (bytes memory data) {\n data = new bytes(length);\n assembly {\n returndatacopy(add(data, 32), offset, length)\n }\n }\n\n /**\n * @dev Reverts with the return data from the most recent external call.\n */\n function propagateRevert() internal pure {\n assembly {\n returndatacopy(0, 0, returndatasize())\n revert(0, returndatasize())\n }\n }\n\n /**\n * @dev An optimised function to compute the sha3 of the lower-case\n * hexadecimal representation of an Ethereum address.\n * @param addr The address to hash\n * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the\n * input address.\n */\n function sha3HexAddress(address addr) internal pure returns (bytes32 ret) {\n assembly {\n for {\n let i := 40\n } gt(i, 0) {\n\n } {\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n }\n\n ret := keccak256(0, 40)\n }\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ~0.8.17;\n\nlibrary BytesUtils {\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" + }, + "@ensdomains/evm-verifier/contracts/EVMProofHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport {RLPReader} from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport {Bytes} from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport {SecureMerkleTrie} from \"./SecureMerkleTrie.sol\";\n\nstruct StateProof {\n bytes[] stateTrieWitness; // Witness proving the `storageRoot` against a state root.\n bytes[][] storageProofs; // An array of proofs of individual storage elements \n}\n\nuint8 constant OP_CONSTANT = 0x00;\nuint8 constant OP_BACKREF = 0x20;\nuint8 constant FLAG_DYNAMIC = 0x01;\n\nlibrary EVMProofHelper {\n using Bytes for bytes;\n\n error AccountNotFound(address);\n error UnknownOpcode(uint8);\n error InvalidSlotSize(uint256 size);\n\n /**\n * @notice Get the storage root for the provided merkle proof\n * @param stateRoot The state root the witness was generated against\n * @param target The address we are fetching a storage root for\n * @param witness A witness proving the value of the storage root for `target`.\n * @return The storage root retrieved from the provided state root\n */\n function getStorageRoot(bytes32 stateRoot, address target, bytes[] memory witness) private pure returns (bytes32) {\n (bool exists, bytes memory encodedResolverAccount) = SecureMerkleTrie.get(\n abi.encodePacked(target),\n witness,\n stateRoot\n );\n if(!exists) {\n revert AccountNotFound(target);\n }\n RLPReader.RLPItem[] memory accountState = RLPReader.readList(encodedResolverAccount);\n return bytes32(RLPReader.readBytes(accountState[2]));\n }\n\n /**\n * @notice Prove whether the provided storage slot is part of the storageRoot\n * @param storageRoot the storage root for the account that contains the storage slot\n * @param slot The storage key we are fetching the value of\n * @param witness the StorageProof struct containing the necessary proof data\n * @return The retrieved storage proof value or 0x if the storage slot is empty\n */\n function getSingleStorageProof(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns (bytes memory) {\n (bool exists, bytes memory retrievedValue) = SecureMerkleTrie.get(\n abi.encodePacked(slot),\n witness,\n storageRoot\n );\n if(!exists) {\n // Nonexistent values are treated as zero.\n return \"\";\n }\n return RLPReader.readBytes(retrievedValue);\n }\n\n function getFixedValue(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns(bytes32) {\n bytes memory value = getSingleStorageProof(storageRoot, slot, witness);\n // RLP encoded storage slots are stored without leading 0 bytes.\n // Casting to bytes32 appends trailing 0 bytes, so we have to bit shift to get the \n // original fixed-length representation back.\n return bytes32(value) >> (256 - 8 * value.length);\n }\n\n function executeOperation(bytes1 operation, bytes[] memory constants, bytes[] memory values) private pure returns(bytes memory) {\n uint8 opcode = uint8(operation) & 0xe0;\n uint8 operand = uint8(operation) & 0x1f;\n\n if(opcode == OP_CONSTANT) {\n return constants[operand];\n } else if(opcode == OP_BACKREF) {\n return values[operand];\n } else {\n revert UnknownOpcode(opcode);\n }\n }\n\n function computeFirstSlot(bytes32 command, bytes[] memory constants, bytes[] memory values) private pure returns(bool isDynamic, uint256 slot) {\n uint8 flags = uint8(command[0]);\n isDynamic = (flags & FLAG_DYNAMIC) != 0;\n\n bytes memory slotData = executeOperation(command[1], constants, values);\n require(slotData.length == 32, \"First path element must be 32 bytes\");\n slot = uint256(bytes32(slotData));\n\n for(uint256 j = 2; j < 32 && command[j] != 0xff; j++) {\n bytes memory index = executeOperation(command[j], constants, values);\n slot = uint256(keccak256(abi.encodePacked(index, slot)));\n }\n }\n\n function getDynamicValue(bytes32 storageRoot, uint256 slot, StateProof memory proof, uint256 proofIdx) private pure returns(bytes memory value, uint256 newProofIdx) {\n uint256 firstValue = uint256(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n if(firstValue & 0x01 == 0x01) {\n // Long value: first slot is `length * 2 + 1`, following slots are data.\n uint256 length = (firstValue - 1) / 2;\n value = \"\";\n slot = uint256(keccak256(abi.encodePacked(slot)));\n // This is horribly inefficient - O(n^2). A better approach would be to build an array of words and concatenate them\n // all at once, but we're trying to avoid writing new library code.\n while(length > 0) {\n if(length < 32) {\n value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]).slice(0, length));\n length = 0;\n } else {\n value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]));\n length -= 32;\n }\n }\n return (value, proofIdx);\n } else {\n // Short value: least significant byte is `length * 2`, other bytes are data.\n uint256 length = (firstValue & 0xFF) / 2;\n return (abi.encode(firstValue).slice(0, length), proofIdx);\n }\n }\n\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes32 stateRoot, StateProof memory proof) internal pure returns(bytes[] memory values) {\n bytes32 storageRoot = getStorageRoot(stateRoot, target, proof.stateTrieWitness);\n uint256 proofIdx = 0;\n values = new bytes[](commands.length);\n for(uint256 i = 0; i < commands.length; i++) {\n bytes32 command = commands[i];\n (bool isDynamic, uint256 slot) = computeFirstSlot(command, constants, values);\n if(!isDynamic) {\n values[i] = abi.encode(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n if(values[i].length > 32) {\n revert InvalidSlotSize(values[i].length);\n }\n } else {\n (values[i], proofIdx) = getDynamicValue(storageRoot, slot, proof, proofIdx);\n }\n }\n }\n}" + }, + "@ensdomains/evm-verifier/contracts/IEVMVerifier.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\ninterface IEVMVerifier {\n function gatewayURLs() external view returns(string[] memory);\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\n}\n" + }, + "@ensdomains/evm-verifier/contracts/MerkleTrie.sol": { + "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n// as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n// in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\n\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice RLP representation of `NULL`.\n */\n bytes internal constant RLP_NULL = hex\"80\";\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n (bool exists, bytes memory value) = get(_key, _proof, _root);\n return (exists && Bytes.equal(_value, value));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Whether or not the key exists.\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool, bytes memory) {\n TrieNode[] memory proof = _parseProof(_proof);\n (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(\n proof,\n _key,\n _root\n );\n\n bool noRemainder = keyRemainder.length == 0;\n\n require(noRemainder || isFinalNode, \"MerkleTrie: provided proof is invalid\");\n\n bytes memory value = noRemainder ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n return (value.length > 0, value);\n }\n\n /**\n * @notice Walks through a proof using a provided key.\n *\n * @param _proof Inclusion proof to walk through.\n * @param _key Key to use for the walk.\n * @param _root Known root of the trie.\n *\n * @return Length of the final path\n * @return Portion of the key remaining after the walk.\n * @return Whether or not we've hit a dead end.\n */\n // solhint-disable-next-line code-complexity\n function _walkNodePath(\n TrieNode[] memory _proof,\n bytes memory _key,\n bytes32 _root\n )\n private\n pure\n returns (\n uint256,\n bytes memory,\n bool\n )\n {\n uint256 pathLength = 0;\n bytes memory key = Bytes.toNibbles(_key);\n\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n uint256 currentKeyIncrement = 0;\n TrieNode memory currentNode;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < _proof.length; i++) {\n currentNode = _proof[i];\n currentKeyIndex += currentKeyIncrement;\n\n // Keep track of the proof elements we actually need.\n // It's expensive to resize arrays, so this simply reduces gas costs.\n pathLength += 1;\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // We've hit the end of the key\n // meaning the value should be within this branch node.\n break;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIncrement = 1;\n continue;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n require(\n keyRemainder.length >= pathRemainder.length,\n \"MerkleTrie: invalid key length for leaf or extension node\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n if (\n pathRemainder.length == sharedNibbleLength &&\n keyRemainder.length == sharedNibbleLength\n ) {\n // The key within this leaf matches our key exactly.\n // Increment the key index to reflect that we have no remainder.\n currentKeyIndex += sharedNibbleLength;\n }\n\n // We've hit a leaf node, so our next node should be NULL.\n currentNodeID = RLP_NULL;\n break;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n if (sharedNibbleLength != pathRemainder.length) {\n // Our extension node is not identical to the remainder.\n // We've hit the end of this path\n // updates will need to modify this extension.\n currentNodeID = RLP_NULL;\n break;\n } else {\n // Our extension shares some nibbles.\n // Carry on to the next node.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIncrement = sharedNibbleLength;\n continue;\n }\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n return (\n pathLength,\n Bytes.slice(key, currentKeyIndex),\n Bytes.equal(currentNodeID, RLP_NULL)\n );\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Gets the value for a node.\n *\n * @param _node Node to get a value for.\n *\n * @return Node value, as hex bytes.\n */\n function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {\n return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}" + }, + "@ensdomains/evm-verifier/contracts/SecureMerkleTrie.sol": { + "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n// as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n// in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Whether or not the key exists.\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool, bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}" + }, + "@ensdomains/l1-verifier/contracts/L1Verifier.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from \"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport { StateProof, EVMProofHelper } from \"@ensdomains/evm-verifier/contracts/EVMProofHelper.sol\";\n\nstruct L1WitnessData {\n uint256 blockNo;\n bytes blockHeader;\n}\n\ncontract L1Verifier is IEVMVerifier {\n error BlockHeaderHashMismatch(uint256 current, uint256 number, bytes32 expected, bytes32 actual);\n\n string[] _gatewayURLs;\n\n constructor(string[] memory urls) {\n _gatewayURLs = urls;\n }\n\n function gatewayURLs() external view returns(string[] memory) {\n return _gatewayURLs;\n }\n\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values) {\n (L1WitnessData memory l1Data, StateProof memory stateProof) = abi.decode(proof, (L1WitnessData, StateProof));\n if(keccak256(l1Data.blockHeader) != blockhash(l1Data.blockNo)) {\n revert BlockHeaderHashMismatch(block.number, l1Data.blockNo, blockhash(l1Data.blockNo), keccak256(l1Data.blockHeader));\n }\n RLPReader.RLPItem[] memory headerFields = RLPReader.readList(l1Data.blockHeader);\n bytes32 stateRoot = bytes32(RLPReader.readBytes(headerFields[3]));\n return EVMProofHelper.getStorageValues(target, commands, constants, stateRoot, stateProof);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Bytes\n/// @notice Bytes is a library for manipulating byte arrays.\nlibrary Bytes {\n /// @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n /// @notice Slices a byte array with a given starting index and length. Returns a new byte array\n /// as opposed to a pointer to the original array. Will throw if trying to slice more\n /// bytes than exist in the array.\n /// @param _bytes Byte array to slice.\n /// @param _start Starting index of the slice.\n /// @param _length Length of the slice.\n /// @return Slice of the input byte array.\n function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } { mstore(mc, mload(cc)) }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /// @notice Slices a byte array with a given starting index up to the end of the original byte\n /// array. Returns a new array rathern than a pointer to the original.\n /// @param _bytes Byte array to slice.\n /// @param _start Starting index of the slice.\n /// @return Slice of the input byte array.\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /// @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n /// Resulting nibble array will be exactly twice as long as the input byte array.\n /// @param _bytes Input byte array to convert.\n /// @return Resulting nibble array.\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n bytes memory _nibbles;\n assembly {\n // Grab a free memory offset for the new array\n _nibbles := mload(0x40)\n\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Calculate the length of the new nibble array\n // This is the length of the input array times 2\n let nibblesLength := shl(0x01, bytesLength)\n\n // Update the free memory pointer to allocate memory for the new array.\n // To do this, we add the length of the new array + 32 bytes for the array length\n // rounded up to the nearest 32 byte boundary to the current free memory pointer.\n mstore(0x40, add(_nibbles, and(not(0x1F), add(nibblesLength, 0x3F))))\n\n // Store the length of the new array in memory\n mstore(_nibbles, nibblesLength)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(_nibbles, 0x20)\n\n // Loop through each byte in the input array\n for { let i := 0x00 } lt(i, bytesLength) { i := add(i, 0x01) } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n return _nibbles;\n }\n\n /// @notice Compares two byte arrays by comparing their keccak256 hashes.\n /// @param _bytes First byte array to compare.\n /// @param _other Second byte array to compare.\n /// @return True if the two byte arrays are equal, false otherwise.\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/// @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n/// @title RLPReader\n/// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n/// from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n/// various tweaks to improve readability.\nlibrary RLPReader {\n /// @notice Custom pointer type to avoid confusion between pointers and uint256s.\n type MemoryPointer is uint256;\n\n /// @notice RLP item types.\n /// @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n /// @custom:value LIST_ITEM Represents an RLP list item.\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /// @notice Struct representing an RLP item.\n /// @custom:field length Length of the RLP item.\n /// @custom:field ptr Pointer to the RLP item in memory.\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /// @notice Max list length that this library will accept.\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /// @notice Converts bytes to a reference to memory position and length.\n /// @param _in Input bytes to convert.\n /// @return out_ Output memory reference.\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) {\n // Empty arrays are not RLP items.\n require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n out_ = RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /// @notice Reads an RLP list value into a list of RLP items.\n /// @param _in RLP list value.\n /// @return out_ Decoded RLP list items.\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(itemType == RLPItemType.LIST_ITEM, \"RLPReader: decoded item type for list is not a list item\");\n\n require(listOffset + listLength == _in.length, \"RLPReader: list item has an invalid data remainder\");\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n out_ = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength,) = _decodeLength(\n RLPItem({ length: _in.length - offset, ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out_[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out_, itemCount)\n }\n }\n\n /// @notice Reads an RLP list value into a list of RLP items.\n /// @param _in RLP list value.\n /// @return out_ Decoded RLP list items.\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) {\n out_ = readList(toRLPItem(_in));\n }\n\n /// @notice Reads an RLP bytes value into bytes.\n /// @param _in RLP bytes value.\n /// @return out_ Decoded bytes.\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(itemType == RLPItemType.DATA_ITEM, \"RLPReader: decoded item type for bytes is not a data item\");\n\n require(_in.length == itemOffset + itemLength, \"RLPReader: bytes value contains an invalid remainder\");\n\n out_ = _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /// @notice Reads an RLP bytes value into bytes.\n /// @param _in RLP bytes value.\n /// @return out_ Decoded bytes.\n function readBytes(bytes memory _in) internal pure returns (bytes memory out_) {\n out_ = readBytes(toRLPItem(_in));\n }\n\n /// @notice Reads the raw bytes of an RLP item.\n /// @param _in RLP item to read.\n /// @return out_ Raw RLP bytes.\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n out_ = _copy(_in.ptr, 0, _in.length);\n }\n\n /// @notice Decodes the length of an RLP item.\n /// @param _in RLP item to decode.\n /// @return offset_ Offset of the encoded data.\n /// @return length_ Length of the encoded data.\n /// @return type_ RLP item type (LIST_ITEM or DATA_ITEM).\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (uint256 offset_, uint256 length_, RLPItemType type_)\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen, \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(strLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long string)\");\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(_in.length > listLen, \"RLPReader: length of content must be greater than list length (short list)\");\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(listLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long list)\");\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /// @notice Copies the bytes from a memory location.\n /// @param _src Pointer to the location to read from.\n /// @param _offset Offset to start reading from.\n /// @param _length Number of bytes to read.\n /// @return out_ Copied bytes.\n function _copy(MemoryPointer _src, uint256 _offset, uint256 _length) private pure returns (bytes memory out_) {\n out_ = new bytes(_length);\n if (_length == 0) {\n return out_;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out_, 32)\n let i := 0\n for { } lt(i, _length) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) }\n\n if gt(i, _length) { mstore(add(dest, _length), 0) }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../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 * By default, the owner account will be the one that deploys the contract. This\n * can 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 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\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 require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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 require(newOwner != address(0), \"Ownable: new owner is the zero address\");\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 v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\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 *\n * _Available since v4.1._\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/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n * function (like regular Solidity function calls).\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 * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\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 * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n return\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n isValidERC1271SignatureNow(signer, hash, signature);\n }\n\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n * against the signer smart contract using ERC1271.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidERC1271SignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length >= 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@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" + }, + "@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 // → `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 + (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" + }, + "@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" + }, + "@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" + }, + "contracts/DefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"./IDefaultReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * A fallback reverser resolver to resolve when L2 reverse resolver has no names set.\n * The contract will be set under \"default.reverse\" namespace\n * It can only be set by EOA as contract accounts are chain dependent.\n */\ncontract DefaultReverseResolver is\n Ownable,\n IDefaultReverseResolver,\n ERC165,\n SignatureReverseResolver\n{\n using ECDSA for bytes32;\n using BytesUtils for bytes;\n // The namehash of 'default.reverse'\n bytes32 private constant DEFAULT_REVERSE_NODE =\n 0x53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd312;\n\n /**\n * @dev Constructor\n */\n constructor() SignatureReverseResolver(DEFAULT_REVERSE_NODE, 0) {}\n\n function isAuthorised(address addr) internal view override returns (bool) {\n if (addr != msg.sender) {\n revert Unauthorised();\n }\n }\n\n /*\n * Returns the name associated with an address, for reverse records.\n * This function is non ENSIP standard\n * @param address The ENS address to query.\n * @return The associated name.\n */\n function name(address addr) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_names[recordVersions[node]][node];\n }\n\n /*\n * Returns the text data associated with an address and key.\n * @param address The ENS address to query.\n * @param key The text data key to query.\n * @return The associated text data.\n */\n function text(\n address addr,\n string memory key\n ) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view override(ERC165, SignatureReverseResolver) returns (bool) {\n return\n interfaceID == type(IDefaultReverseResolver).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "contracts/deps.sol": { + "content": "import {L1Verifier} from '@ensdomains/l1-verifier/contracts/L1Verifier.sol';\nimport '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol';\nimport '@ensdomains/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol';\n// Storage slot\n// ┌────────────────────┬───────────────────┬──────────────┬\n// │ contract │ state_variable │ storage_slot │\n// ├────────────────────┼───────────────────┼──────────────┼\n// │ L2ReverseRegistrar │ _owner │ 0 │\n// │ L2ReverseRegistrar │ lastUpdated │ 1 │\n// │ L2ReverseRegistrar │ versionable_texts │ 2 │\n// │ L2ReverseRegistrar │ versionable_names │ 3 │\n// │ L2ReverseRegistrar │ recordVersions │ 4 │\n" + }, + "contracts/IDefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface IDefaultReverseResolver {\n function name(address addr) external view returns (string memory);\n\n function text(\n address addr,\n string memory key\n ) external view returns (string memory);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "storageLayout" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/crosschain-reverse-resolver/deployments/sepolia/solcInputs/776c7519acf1eee16c4cde4c93293488.json b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/776c7519acf1eee16c4cde4c93293488.json new file mode 100644 index 00000000..20fec410 --- /dev/null +++ b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/776c7519acf1eee16c4cde4c93293488.json @@ -0,0 +1,102 @@ +{ + "language": "Solidity", + "sources": { + "@ensdomains/ens-contracts/contracts/registry/ENS.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n // Logged when the owner of a node assigns a new owner to a subnode.\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n // Logged when the owner of a node transfers ownership to a new account.\n event Transfer(bytes32 indexed node, address owner);\n\n // Logged when the resolver for a node changes.\n event NewResolver(bytes32 indexed node, address resolver);\n\n // Logged when the TTL of a node changes\n event NewTTL(bytes32 indexed node, uint64 ttl);\n\n // Logged when an operator is added or removed.\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n function setRecord(\n bytes32 node,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner\n ) external returns (bytes32);\n\n function setResolver(bytes32 node, address resolver) external;\n\n function setOwner(bytes32 node, address owner) external;\n\n function setTTL(bytes32 node, uint64 ttl) external;\n\n function setApprovalForAll(address operator, bool approved) external;\n\n function owner(bytes32 node) external view returns (address);\n\n function resolver(bytes32 node) external view returns (address);\n\n function ttl(bytes32 node) external view returns (uint64);\n\n function recordExists(bytes32 node) external view returns (bool);\n\n function isApprovedForAll(\n address owner,\n address operator\n ) external view returns (bool);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IExtendedResolver {\n function resolve(\n bytes memory name,\n bytes memory data\n ) external view returns (bytes memory);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface INameResolver {\n event NameChanged(bytes32 indexed node, string name);\n\n /**\n * Returns the name associated with an ENS node, for reverse records.\n * Defined in EIP181.\n * @param node The ENS node to query.\n * @return The associated name.\n */\n function name(bytes32 node) external view returns (string memory);\n}\n" + }, + "@ensdomains/ens-contracts/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" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/ISignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ISignatureReverseResolver {\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\n event ReverseClaimed(address indexed addr, bytes32 indexed node);\n event NameChanged(bytes32 indexed node, string name);\n event TextChanged(\n bytes32 indexed node,\n string indexed indexedKey,\n string key,\n string value\n );\n\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) external;\n\n function node(address addr) external view returns (bytes32);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./ISignatureReverseResolver.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../root/Controllable.sol\";\nimport \"../utils/LowLevelCallUtils.sol\";\n\nerror InvalidSignature();\nerror SignatureOutOfDate();\nerror Unauthorised();\n\ncontract SignatureReverseResolver is Ownable, ISignatureReverseResolver {\n using ECDSA for bytes32;\n mapping(bytes32 => uint256) public lastUpdated;\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\n mapping(bytes32 => uint64) internal recordVersions;\n\n bytes32 public immutable ParentNode;\n uint256 public immutable coinType;\n\n /*\n * @dev Constructor\n * @param ParentNode The namespace to set.\n * @param _coinType The cointype converted from the chainId of the chain this contract is deployed to.\n */\n constructor(bytes32 _ParentNode, uint256 _coinType) {\n ParentNode = _ParentNode;\n coinType = _coinType;\n }\n\n modifier authorised(address addr) {\n isAuthorised(addr);\n _;\n }\n\n modifier authorisedSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) {\n isAuthorisedWithSignature(hash, addr, inceptionDate, signature);\n _;\n }\n\n function getLastUpdated(\n bytes32 node\n ) internal view virtual returns (uint256) {\n return lastUpdated[node];\n }\n\n function isAuthorised(address addr) internal view virtual returns (bool) {}\n\n function isAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) internal view returns (bool) {\n bytes32 message = keccak256(\n abi.encodePacked(hash, addr, inceptionDate, coinType)\n ).toEthSignedMessageHash();\n bytes32 node = _getNamehash(addr);\n\n if (!SignatureChecker.isValidSignatureNow(addr, message, signature)) {\n revert InvalidSignature();\n }\n\n if (\n inceptionDate <= lastUpdated[node] || // must be newer than current record\n inceptionDate / 1000 >= block.timestamp // must be in the past\n ) {\n revert SignatureOutOfDate();\n }\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param name The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setNameForAddrWithSignature\n .selector,\n name\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setName(node, name, inceptionDate);\n emit ReverseClaimed(addr, node);\n return node;\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param key The key of the text record\n * @param value The value of the text record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setTextForAddrWithSignature\n .selector,\n key,\n value\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setText(node, key, value, inceptionDate);\n return node;\n }\n\n function _setText(\n bytes32 node,\n string calldata key,\n string calldata value,\n uint256 inceptionDate\n ) internal {\n versionable_texts[recordVersions[node]][node][key] = value;\n _setLastUpdated(node, inceptionDate);\n emit TextChanged(node, key, key, 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 ) internal view returns (string memory) {\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n function _setName(\n bytes32 node,\n string memory newName,\n uint256 inceptionDate\n ) internal virtual {\n versionable_names[recordVersions[node]][node] = newName;\n _setLastUpdated(node, inceptionDate);\n emit NameChanged(node, newName);\n }\n\n function _name(bytes32 node) internal view returns (string memory) {\n return versionable_names[recordVersions[node]][node];\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n */\n function _clearRecords(address addr) internal {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n bytes32 reverseNode = keccak256(\n abi.encodePacked(ParentNode, labelHash)\n );\n recordVersions[reverseNode]++;\n emit VersionChanged(reverseNode, recordVersions[reverseNode]);\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n * @param signature A signature proving ownership of the node.\n */\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver.clearRecordsWithSignature.selector\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n {\n _clearRecords(addr);\n }\n\n /**\n * @dev Returns the node hash for a given account's reverse records.\n * @param addr The address to hash\n * @return The ENS node hash.\n */\n function node(address addr) public view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(\n ParentNode,\n LowLevelCallUtils.sha3HexAddress(addr)\n )\n );\n }\n\n function _getNamehash(address addr) internal view returns (bytes32) {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n return keccak256(abi.encodePacked(ParentNode, labelHash));\n }\n\n function _setLastUpdated(bytes32 node, uint256 inceptionDate) internal {\n lastUpdated[node] = inceptionDate;\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view virtual returns (bool) {\n return interfaceID == type(ISignatureReverseResolver).interfaceId;\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/root/Controllable.sol": { + "content": "pragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Controllable is Ownable {\n mapping(address => bool) public controllers;\n\n event ControllerChanged(address indexed controller, bool enabled);\n\n modifier onlyController() {\n require(\n controllers[msg.sender],\n \"Controllable: Caller is not a controller\"\n );\n _;\n }\n\n function setController(address controller, bool enabled) public onlyOwner {\n controllers[controller] = enabled;\n emit ControllerChanged(controller, enabled);\n }\n}\n" + }, + "@ensdomains/ens-contracts/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 r, bool valid) {\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 r := or(shl(8, r), 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" + }, + "@ensdomains/ens-contracts/contracts/utils/LowLevelCallUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.13;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nlibrary LowLevelCallUtils {\n // This is the hex encoding of the string 'abcdefghijklmnopqrstuvwxyz'\n // It is used as a constant to lookup the characters of the hex address\n bytes32 constant lookup =\n 0x3031323334353637383961626364656600000000000000000000000000000000;\n using Address for address;\n\n /**\n * @dev Makes a static call to the specified `target` with `data`. Return data can be fetched with\n * `returnDataSize` and `readReturnData`.\n * @param target The address to staticcall.\n * @param data The data to pass to the call.\n * @return success True if the call succeeded, or false if it reverts.\n */\n function functionStaticCall(\n address target,\n bytes memory data\n ) internal view returns (bool success) {\n require(\n target.isContract(),\n \"LowLevelCallUtils: static call to non-contract\"\n );\n assembly {\n success := staticcall(\n gas(),\n target,\n add(data, 32),\n mload(data),\n 0,\n 0\n )\n }\n }\n\n /**\n * @dev Returns the size of the return data of the most recent external call.\n */\n function returnDataSize() internal pure returns (uint256 len) {\n assembly {\n len := returndatasize()\n }\n }\n\n /**\n * @dev Reads return data from the most recent external call.\n * @param offset Offset into the return data.\n * @param length Number of bytes to return.\n */\n function readReturnData(\n uint256 offset,\n uint256 length\n ) internal pure returns (bytes memory data) {\n data = new bytes(length);\n assembly {\n returndatacopy(add(data, 32), offset, length)\n }\n }\n\n /**\n * @dev Reverts with the return data from the most recent external call.\n */\n function propagateRevert() internal pure {\n assembly {\n returndatacopy(0, 0, returndatasize())\n revert(0, returndatasize())\n }\n }\n\n /**\n * @dev An optimised function to compute the sha3 of the lower-case\n * hexadecimal representation of an Ethereum address.\n * @param addr The address to hash\n * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the\n * input address.\n */\n function sha3HexAddress(address addr) internal pure returns (bytes32 ret) {\n assembly {\n for {\n let i := 40\n } gt(i, 0) {\n\n } {\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n }\n\n ret := keccak256(0, 40)\n }\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ~0.8.17;\n\nlibrary BytesUtils {\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" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../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 * By default, the owner account will be the one that deploys the contract. This\n * can 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 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\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 require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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 require(newOwner != address(0), \"Ownable: new owner is the zero address\");\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 v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\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 *\n * _Available since v4.1._\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/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n * function (like regular Solidity function calls).\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 * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\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 * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n return\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n isValidERC1271SignatureNow(signer, hash, signature);\n }\n\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n * against the signer smart contract using ERC1271.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidERC1271SignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length >= 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@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" + }, + "@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 // → `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 + (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" + }, + "@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" + }, + "@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" + }, + "contracts/DefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"./IDefaultReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport {ITextResolver} from \"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\";\nimport {INameResolver} from \"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\";\nimport \"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\";\n\n/**\n * A fallback reverser resolver to resolve when L2 reverse resolver has no names set.\n * The contract will be set under \"default.reverse\" namespace\n * It can only be set by EOA as contract accounts are chain dependent.\n */\ncontract DefaultReverseResolver is\n Ownable,\n IDefaultReverseResolver,\n IExtendedResolver,\n ERC165,\n SignatureReverseResolver\n{\n uint256 constant ADDRESS_LENGTH = 40;\n using ECDSA for bytes32;\n using BytesUtils for bytes;\n // The namehash of 'default.reverse'\n bytes32 private constant DEFAULT_REVERSE_NODE =\n 0x53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd312;\n\n /**\n * @dev Constructor\n */\n constructor() SignatureReverseResolver(DEFAULT_REVERSE_NODE, 0) {}\n\n function isAuthorised(address addr) internal view override returns (bool) {\n if (addr != msg.sender) {\n revert Unauthorised();\n }\n }\n\n /*\n * Returns the name associated with an address, for reverse records.\n * This function is non ENSIP standard\n * @param address The ENS address to query.\n * @return The associated name.\n */\n function name(address addr) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_names[recordVersions[node]][node];\n }\n\n /*\n * Returns the text data associated with an address and key.\n * @param address The ENS address to query.\n * @param key The text data key to query.\n * @return The associated text data.\n */\n function text(\n address addr,\n string memory key\n ) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n /*\n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\n * @param name DNS encoded ENS name to query\n * @param data The actual calldata\n * @return result result of the call\n */\n function resolve(bytes calldata _name, bytes calldata data) external view returns (bytes memory result) {\n bytes4 selector = bytes4(data);\n (address addr,) = HexUtils.hexToAddress(_name, 1, ADDRESS_LENGTH + 1);\n if (selector == INameResolver.name.selector) {\n return bytes(name(addr));\n }\n if (selector == ITextResolver.text.selector) {\n (,string memory key) = abi.decode(data[4:], (bytes32, string));\n return bytes(text(addr, key));\n }\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view override(ERC165, SignatureReverseResolver) returns (bool) {\n return\n interfaceID == type(IDefaultReverseResolver).interfaceId ||\n interfaceID == type(IExtendedResolver).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "contracts/IDefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface IDefaultReverseResolver {\n function name(address addr) external view returns (string memory);\n\n function text(\n address addr,\n string memory key\n ) external view returns (string memory);\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "storageLayout" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/crosschain-reverse-resolver/deployments/sepolia/solcInputs/7cc7da1092d13c01f4d5f27229751af2.json b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/7cc7da1092d13c01f4d5f27229751af2.json new file mode 100644 index 00000000..90284699 --- /dev/null +++ b/crosschain-reverse-resolver/deployments/sepolia/solcInputs/7cc7da1092d13c01f4d5f27229751af2.json @@ -0,0 +1,150 @@ +{ + "language": "Solidity", + "sources": { + "@ensdomains/ens-contracts/contracts/registry/ENS.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n // Logged when the owner of a node assigns a new owner to a subnode.\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n // Logged when the owner of a node transfers ownership to a new account.\n event Transfer(bytes32 indexed node, address owner);\n\n // Logged when the resolver for a node changes.\n event NewResolver(bytes32 indexed node, address resolver);\n\n // Logged when the TTL of a node changes\n event NewTTL(bytes32 indexed node, uint64 ttl);\n\n // Logged when an operator is added or removed.\n event ApprovalForAll(\n address indexed owner,\n address indexed operator,\n bool approved\n );\n\n function setRecord(\n bytes32 node,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeRecord(\n bytes32 node,\n bytes32 label,\n address owner,\n address resolver,\n uint64 ttl\n ) external;\n\n function setSubnodeOwner(\n bytes32 node,\n bytes32 label,\n address owner\n ) external returns (bytes32);\n\n function setResolver(bytes32 node, address resolver) external;\n\n function setOwner(bytes32 node, address owner) external;\n\n function setTTL(bytes32 node, uint64 ttl) external;\n\n function setApprovalForAll(address operator, bool approved) external;\n\n function owner(bytes32 node) external view returns (address);\n\n function resolver(bytes32 node) external view returns (address);\n\n function ttl(bytes32 node) external view returns (uint64);\n\n function recordExists(bytes32 node) external view returns (bool);\n\n function isApprovedForAll(\n address owner,\n address operator\n ) external view returns (bool);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/IMulticallable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IMulticallable {\n function multicall(\n bytes[] calldata data\n ) external returns (bytes[] memory results);\n\n function multicallWithNodeCheck(\n bytes32,\n bytes[] calldata data\n ) external returns (bytes[] memory results);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/Multicallable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"./IMulticallable.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\nabstract contract Multicallable is IMulticallable, ERC165 {\n function _multicall(\n bytes32 nodehash,\n bytes[] calldata data\n ) internal returns (bytes[] memory results) {\n results = new bytes[](data.length);\n for (uint256 i = 0; i < data.length; i++) {\n if (nodehash != bytes32(0)) {\n bytes32 txNamehash = bytes32(data[i][4:36]);\n require(\n txNamehash == nodehash,\n \"multicall: All records must have a matching namehash\"\n );\n }\n (bool success, bytes memory result) = address(this).delegatecall(\n data[i]\n );\n require(success);\n results[i] = result;\n }\n return results;\n }\n\n // This function provides an extra security check when called\n // from priviledged contracts (such as EthRegistrarController)\n // that can set records on behalf of the node owners\n function multicallWithNodeCheck(\n bytes32 nodehash,\n bytes[] calldata data\n ) external returns (bytes[] memory results) {\n return _multicall(nodehash, data);\n }\n\n function multicall(\n bytes[] calldata data\n ) public override returns (bytes[] memory results) {\n return _multicall(bytes32(0), data);\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view virtual override returns (bool) {\n return\n interfaceID == type(IMulticallable).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IExtendedResolver {\n function resolve(\n bytes memory name,\n bytes memory data\n ) external view returns (bytes memory);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface INameResolver {\n event NameChanged(bytes32 indexed node, string name);\n\n /**\n * Returns the name associated with an ENS node, for reverse records.\n * Defined in EIP181.\n * @param node The ENS node to query.\n * @return The associated name.\n */\n function name(bytes32 node) external view returns (string memory);\n}\n" + }, + "@ensdomains/ens-contracts/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" + }, + "@ensdomains/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.4;\n\ninterface IVersionableResolver {\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\n\n function recordVersions(bytes32 node) external view returns (uint64);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/IL2ReverseRegistrar.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface IL2ReverseRegistrar {\n function setName(string memory name) external returns (bytes32);\n\n function setNameForAddr(\n address addr,\n string memory name\n ) external returns (bytes32);\n\n function setNameForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function setText(\n string calldata key,\n string calldata value\n ) external returns (bytes32);\n\n function setTextForAddr(\n address addr,\n string calldata key,\n string calldata value\n ) external returns (bytes32);\n\n function setTextForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function clearRecords(address addr) external;\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/ISignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface ISignatureReverseResolver {\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n ) external returns (bytes32);\n\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) external;\n\n function node(address addr) external view returns (bytes32);\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./IL2ReverseRegistrar.sol\";\nimport \"./SignatureReverseResolver.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../resolvers/profiles/ITextResolver.sol\";\nimport \"../resolvers/profiles/INameResolver.sol\";\nimport \"../root/Controllable.sol\";\nimport \"../resolvers/Multicallable.sol\";\nimport \"../utils/LowLevelCallUtils.sol\";\n\nerror NotOwnerOfContract();\n\n// @note Inception date\n// The inception date is in milliseconds, and so will be divided by 1000\n// when comparing to block.timestamp. This means that the date will be\n// rounded down to the nearest second.\n\ncontract L2ReverseRegistrar is\n Multicallable,\n Ownable,\n ITextResolver,\n INameResolver,\n IL2ReverseRegistrar,\n SignatureReverseResolver\n{\n using ECDSA for bytes32;\n\n bytes32 public immutable L2ReverseNode;\n\n /**\n * @dev Constructor\n */\n constructor(\n bytes32 _L2ReverseNode,\n uint256 _coinType\n ) SignatureReverseResolver(_L2ReverseNode, _coinType) {\n L2ReverseNode = _L2ReverseNode;\n // coinType = _coinType;\n }\n\n modifier ownerAndAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n address owner,\n uint256 inceptionDate,\n bytes memory signature\n ) {\n isOwnerAndAuthorisedWithSignature(\n hash,\n addr,\n owner,\n inceptionDate,\n signature\n );\n _;\n }\n\n function isAuthorised(address addr) internal view override returns (bool) {\n if (addr != msg.sender && !ownsContract(addr, msg.sender)) {\n revert Unauthorised();\n }\n }\n\n function isOwnerAndAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n address owner,\n uint256 inceptionDate,\n bytes memory signature\n ) internal view returns (bool) {\n bytes32 message = keccak256(\n abi.encodePacked(hash, addr, owner, inceptionDate, coinType)\n ).toEthSignedMessageHash();\n bytes32 node = _getNamehash(addr);\n\n if (!ownsContract(addr, owner)) {\n revert NotOwnerOfContract();\n }\n\n if (\n !SignatureChecker.isValidERC1271SignatureNow(\n owner,\n message,\n signature\n )\n ) {\n revert InvalidSignature();\n }\n\n if (\n inceptionDate <= lastUpdated[node] || // must be newer than current record\n inceptionDate / 1000 >= block.timestamp // must be in the past\n ) {\n revert SignatureOutOfDate();\n }\n }\n\n /**\n * @dev Sets the name for a contract that is owned by a SCW using a signature\n * @param contractAddr The reverse node to set\n * @param owner The owner of the contract (via Ownable)\n * @param name The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The signature of an address that will return true on isValidSignature for the owner\n * @return The ENS node hash of the reverse record.\n */\n function setNameForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n ownerAndAuthorisedWithSignature(\n keccak256(\n abi.encodePacked(\n IL2ReverseRegistrar\n .setNameForAddrWithSignatureAndOwnable\n .selector,\n name\n )\n ),\n contractAddr,\n owner,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(contractAddr);\n _setName(node, name, inceptionDate);\n emit ReverseClaimed(contractAddr, node);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the calling account.\n * @param name The name to set for this address.\n * @return The ENS node hash of the reverse record.\n */\n function setName(string memory name) public override returns (bytes32) {\n return setNameForAddr(msg.sender, name);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the addr provided account.\n * Can be used if the addr is a contract that is owned by a SCW.\n * @param name The name to set for this address.\n * @return The ENS node hash of the reverse record.\n */\n\n function setNameForAddr(\n address addr,\n string memory name\n ) public authorised(addr) returns (bytes32) {\n bytes32 node = _getNamehash(addr);\n _setName(node, name, block.timestamp);\n emit ReverseClaimed(addr, node);\n return node;\n }\n\n /**\n * @dev Sets the name for a contract that is owned by a SCW using a signature\n * @param contractAddr The reverse node to set\n * @param owner The owner of the contract (via Ownable)\n * @param key The name of the reverse record\n * @param value The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The signature of an address that will return true on isValidSignature for the owner\n * @return The ENS node hash of the reverse record.\n */\n function setTextForAddrWithSignatureAndOwnable(\n address contractAddr,\n address owner,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n ownerAndAuthorisedWithSignature(\n keccak256(\n abi.encodePacked(\n IL2ReverseRegistrar\n .setTextForAddrWithSignatureAndOwnable\n .selector,\n key,\n value\n )\n ),\n contractAddr,\n owner,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(contractAddr);\n _setText(node, key, value, inceptionDate);\n }\n\n /**\n * @dev Sets the `name()` record for the reverse ENS record associated with\n * the calling account.\n * @param key The key for this text record.\n * @param value The value to set for this text record.\n * @return The ENS node hash of the reverse record.\n */\n function setText(\n string calldata key,\n string calldata value\n ) public override returns (bytes32) {\n return setTextForAddr(msg.sender, key, value);\n }\n\n /**\n * @dev Sets the `text(key)` record for the reverse ENS record associated with\n * the addr provided account.\n * @param key The key for this text record.\n * @param value The value to set for this text record.\n * @return The ENS node hash of the reverse record.\n */\n\n function setTextForAddr(\n address addr,\n string calldata key,\n string calldata value\n ) public override authorised(addr) returns (bytes32) {\n bytes32 node = _getNamehash(addr);\n _setText(node, key, value, block.timestamp);\n return node;\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 virtual override returns (string memory) {\n return _text(node, key);\n }\n\n /**\n * Returns the name associated with an ENS node, for reverse records.\n * Defined in EIP181.\n * @param node The ENS node to query.\n * @return The associated name.\n */\n function name(\n bytes32 node\n ) external view virtual override returns (string memory) {\n return _name(node);\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n */\n function clearRecords(address addr) public virtual authorised(addr) {\n _clearRecords(addr);\n }\n\n function ownsContract(\n address contractAddr,\n address addr\n ) internal view returns (bool) {\n try Ownable(contractAddr).owner() returns (address owner) {\n return owner == addr;\n } catch {\n return false;\n }\n }\n\n function supportsInterface(\n bytes4 interfaceID\n )\n public\n view\n override(Multicallable, SignatureReverseResolver)\n returns (bool)\n {\n return\n interfaceID == type(IL2ReverseRegistrar).interfaceId ||\n interfaceID == type(ITextResolver).interfaceId ||\n interfaceID == type(INameResolver).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"../registry/ENS.sol\";\nimport \"./ISignatureReverseResolver.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../root/Controllable.sol\";\nimport \"../utils/LowLevelCallUtils.sol\";\n\nerror InvalidSignature();\nerror SignatureOutOfDate();\nerror Unauthorised();\n\n// @note Inception date\n// The inception date is in milliseconds, and so will be divided by 1000\n// when comparing to block.timestamp. This means that the date will be\n// rounded down to the nearest second.\n\ncontract SignatureReverseResolver is Ownable, ISignatureReverseResolver {\n using ECDSA for bytes32;\n mapping(bytes32 => uint256) public lastUpdated;\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\n mapping(bytes32 => uint64) internal recordVersions;\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\n event ReverseClaimed(address indexed addr, bytes32 indexed node);\n\n bytes32 public immutable ParentNode;\n uint256 public immutable coinType;\n\n /**\n * @dev Constructor\n */\n constructor(bytes32 _ParentNode, uint256 _coinType) {\n ParentNode = _ParentNode;\n coinType = _coinType;\n }\n\n modifier authorised(address addr) {\n isAuthorised(addr);\n _;\n }\n\n modifier authorisedSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) {\n isAuthorisedWithSignature(hash, addr, inceptionDate, signature);\n _;\n }\n\n function getLastUpdated(\n bytes32 node\n ) internal view virtual returns (uint256) {\n return lastUpdated[node];\n }\n\n function isAuthorised(address addr) internal view virtual returns (bool) {}\n\n function isAuthorisedWithSignature(\n bytes32 hash,\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n ) internal view returns (bool) {\n bytes32 message = keccak256(\n abi.encodePacked(hash, addr, inceptionDate, coinType)\n ).toEthSignedMessageHash();\n bytes32 node = _getNamehash(addr);\n\n if (!SignatureChecker.isValidSignatureNow(addr, message, signature)) {\n revert InvalidSignature();\n }\n\n if (\n inceptionDate <= lastUpdated[node] || // must be newer than current record\n inceptionDate / 1000 >= block.timestamp // must be in the past\n ) {\n revert SignatureOutOfDate();\n }\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param name The name of the reverse record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setNameForAddrWithSignature(\n address addr,\n string memory name,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setNameForAddrWithSignature\n .selector,\n name\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setName(node, name, inceptionDate);\n emit ReverseClaimed(addr, node);\n return node;\n }\n\n /**\n * @dev Sets the name for an addr using a signature that can be verified with ERC1271.\n * @param addr The reverse record to set\n * @param key The key of the text record\n * @param value The value of the text record\n * @param inceptionDate Date from when this signature is valid from\n * @param signature The resolver of the reverse node\n * @return The ENS node hash of the reverse record.\n */\n function setTextForAddrWithSignature(\n address addr,\n string calldata key,\n string calldata value,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver\n .setTextForAddrWithSignature\n .selector,\n key,\n value\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n returns (bytes32)\n {\n bytes32 node = _getNamehash(addr);\n _setText(node, key, value, inceptionDate);\n return node;\n }\n\n function _setText(\n bytes32 node,\n string calldata key,\n string calldata value,\n uint256 inceptionDate\n ) internal {\n versionable_texts[recordVersions[node]][node][key] = value;\n _setLastUpdated(node, inceptionDate);\n // emit TextChanged(node, key, key, 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 ) internal view returns (string memory) {\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n /**\n * Sets the name associated with an ENS node, for reverse records.\n * May only be called by the owner of that node in the ENS registry.\n * @param node The node to update.\n * @param newName name record\n */\n function _setName(\n bytes32 node,\n string memory newName,\n uint256 inceptionDate\n ) internal virtual {\n versionable_names[recordVersions[node]][node] = newName;\n _setLastUpdated(node, inceptionDate);\n // emit NameChanged(node, newName);\n }\n\n function _name(bytes32 node) internal view returns (string memory) {\n return versionable_names[recordVersions[node]][node];\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n */\n function _clearRecords(address addr) internal {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n bytes32 reverseNode = keccak256(\n abi.encodePacked(ParentNode, labelHash)\n );\n recordVersions[reverseNode]++;\n emit VersionChanged(reverseNode, recordVersions[reverseNode]);\n }\n\n /**\n * Increments the record version associated with an ENS node.\n * May only be called by the owner of that node in the ENS registry.\n * @param addr The node to update.\n * @param signature A signature proving ownership of the node.\n */\n function clearRecordsWithSignature(\n address addr,\n uint256 inceptionDate,\n bytes memory signature\n )\n public\n authorisedSignature(\n keccak256(\n abi.encodePacked(\n ISignatureReverseResolver.clearRecordsWithSignature.selector\n )\n ),\n addr,\n inceptionDate,\n signature\n )\n {\n _clearRecords(addr);\n }\n\n /**\n * @dev Returns the node hash for a given account's reverse records.\n * @param addr The address to hash\n * @return The ENS node hash.\n */\n function node(address addr) public view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(\n ParentNode,\n LowLevelCallUtils.sha3HexAddress(addr)\n )\n );\n }\n\n function _getNamehash(address addr) internal view returns (bytes32) {\n bytes32 labelHash = LowLevelCallUtils.sha3HexAddress(addr);\n return keccak256(abi.encodePacked(ParentNode, labelHash));\n }\n\n function _setLastUpdated(bytes32 node, uint256 inceptionDate) internal {\n lastUpdated[node] = inceptionDate;\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view virtual returns (bool) {\n return interfaceID == type(ISignatureReverseResolver).interfaceId;\n // super.supportsInterface(interfaceID);\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/root/Controllable.sol": { + "content": "pragma solidity ^0.8.4;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Controllable is Ownable {\n mapping(address => bool) public controllers;\n\n event ControllerChanged(address indexed controller, bool enabled);\n\n modifier onlyController() {\n require(\n controllers[msg.sender],\n \"Controllable: Caller is not a controller\"\n );\n _;\n }\n\n function setController(address controller, bool enabled) public onlyOwner {\n controllers[controller] = enabled;\n emit ControllerChanged(controller, enabled);\n }\n}\n" + }, + "@ensdomains/ens-contracts/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 r, bool valid) {\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 r := or(shl(8, r), 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" + }, + "@ensdomains/ens-contracts/contracts/utils/LowLevelCallUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.13;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\nlibrary LowLevelCallUtils {\n // This is the hex encoding of the string 'abcdefghijklmnopqrstuvwxyz'\n // It is used as a constant to lookup the characters of the hex address\n bytes32 constant lookup =\n 0x3031323334353637383961626364656600000000000000000000000000000000;\n using Address for address;\n\n /**\n * @dev Makes a static call to the specified `target` with `data`. Return data can be fetched with\n * `returnDataSize` and `readReturnData`.\n * @param target The address to staticcall.\n * @param data The data to pass to the call.\n * @return success True if the call succeeded, or false if it reverts.\n */\n function functionStaticCall(\n address target,\n bytes memory data\n ) internal view returns (bool success) {\n require(\n target.isContract(),\n \"LowLevelCallUtils: static call to non-contract\"\n );\n assembly {\n success := staticcall(\n gas(),\n target,\n add(data, 32),\n mload(data),\n 0,\n 0\n )\n }\n }\n\n /**\n * @dev Returns the size of the return data of the most recent external call.\n */\n function returnDataSize() internal pure returns (uint256 len) {\n assembly {\n len := returndatasize()\n }\n }\n\n /**\n * @dev Reads return data from the most recent external call.\n * @param offset Offset into the return data.\n * @param length Number of bytes to return.\n */\n function readReturnData(\n uint256 offset,\n uint256 length\n ) internal pure returns (bytes memory data) {\n data = new bytes(length);\n assembly {\n returndatacopy(add(data, 32), offset, length)\n }\n }\n\n /**\n * @dev Reverts with the return data from the most recent external call.\n */\n function propagateRevert() internal pure {\n assembly {\n returndatacopy(0, 0, returndatasize())\n revert(0, returndatasize())\n }\n }\n\n /**\n * @dev An optimised function to compute the sha3 of the lower-case\n * hexadecimal representation of an Ethereum address.\n * @param addr The address to hash\n * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the\n * input address.\n */\n function sha3HexAddress(address addr) internal pure returns (bytes32 ret) {\n assembly {\n for {\n let i := 40\n } gt(i, 0) {\n\n } {\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n i := sub(i, 1)\n mstore8(i, byte(and(addr, 0xf), lookup))\n addr := div(addr, 0x10)\n }\n\n ret := keccak256(0, 40)\n }\n }\n}\n" + }, + "@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ~0.8.17;\n\nlibrary BytesUtils {\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" + }, + "@ensdomains/evm-verifier/contracts/EVMFetcher.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from './IEVMVerifier.sol';\nimport { EVMFetchTarget } from './EVMFetchTarget.sol';\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\n\ninterface IEVMGateway {\n function getStorageSlots(address addr, bytes32[] memory commands, bytes[] memory constants) external pure returns(bytes memory witness);\n}\n\nuint8 constant FLAG_DYNAMIC = 0x01;\nuint8 constant OP_CONSTANT = 0x00;\nuint8 constant OP_BACKREF = 0x20;\nuint8 constant OP_END = 0xff;\n\n/**\n * @dev A library to facilitate requesting storage data proofs from contracts, possibly on a different chain.\n * See l1-verifier/test/TestL1.sol for example usage.\n */\nlibrary EVMFetcher {\n uint256 constant MAX_COMMANDS = 32;\n uint256 constant MAX_CONSTANTS = 32; // Must not be greater than 32\n\n using Address for address;\n\n error TooManyCommands(uint256 max);\n error CommandTooLong();\n error InvalidReference(uint256 value, uint256 max);\n error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);\n\n struct EVMFetchRequest {\n IEVMVerifier verifier;\n address target;\n bytes32[] commands;\n uint256 operationIdx;\n bytes[] constants;\n }\n\n /**\n * @dev Creates a request to fetch the value of multiple storage slots from a contract via CCIP-Read, possibly from\n * another chain.\n * Supports dynamic length values and slot numbers derived from other retrieved values.\n * @param verifier An instance of a verifier contract that can provide and verify the storage slot information.\n * @param target The address of the contract to fetch storage proofs for.\n */\n function newFetchRequest(IEVMVerifier verifier, address target) internal pure returns (EVMFetchRequest memory) {\n bytes32[] memory commands = new bytes32[](MAX_COMMANDS);\n bytes[] memory constants = new bytes[](MAX_CONSTANTS);\n assembly {\n mstore(commands, 0) // Set current array length to 0\n mstore(constants, 0)\n } \n return EVMFetchRequest(verifier, target, commands, 0, constants);\n }\n\n /**\n * @dev Starts describing a new fetch request.\n * Paths specify a series of hashing operations to derive the final slot ID.\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\n * lays out storage variables.\n * @param request The request object being operated on.\n * @param baseSlot The base slot ID that forms the root of the path.\n */\n function getStatic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\n bytes32[] memory commands = request.commands;\n uint256 commandIdx = commands.length;\n if(commandIdx > 0 && request.operationIdx < 32) {\n // Terminate previous command\n _addOperation(request, OP_END);\n }\n assembly {\n mstore(commands, add(commandIdx, 1)) // Increment command array length\n }\n if(request.commands.length > MAX_COMMANDS) {\n revert TooManyCommands(MAX_COMMANDS);\n }\n request.operationIdx = 0;\n _addOperation(request, 0);\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\n return request;\n }\n\n /**\n * @dev Starts describing a new fetch request.\n * Paths specify a series of hashing operations to derive the final slot ID.\n * See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html for details on how Solidity\n * lays out storage variables.\n * @param request The request object being operated on.\n * @param baseSlot The base slot ID that forms the root of the path.\n */\n function getDynamic(EVMFetchRequest memory request, uint256 baseSlot) internal pure returns (EVMFetchRequest memory) {\n bytes32[] memory commands = request.commands;\n uint256 commandIdx = commands.length;\n if(commandIdx > 0 && request.operationIdx < 32) {\n // Terminate previous command\n _addOperation(request, OP_END);\n }\n assembly {\n mstore(commands, add(commandIdx, 1)) // Increment command array length\n }\n if(request.commands.length > MAX_COMMANDS) {\n revert TooManyCommands(MAX_COMMANDS);\n }\n request.operationIdx = 0;\n _addOperation(request, FLAG_DYNAMIC);\n _addOperation(request, _addConstant(request, abi.encode(baseSlot)));\n return request;\n }\n\n /**\n * @dev Adds a `uint256` element to the current path.\n * @param request The request object being operated on.\n * @param el The element to add.\n */\n function element(EVMFetchRequest memory request, uint256 el) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n _addOperation(request, _addConstant(request, abi.encode(el)));\n return request;\n }\n\n /**\n * @dev Adds a `bytes32` element to the current path.\n * @param request The request object being operated on.\n * @param el The element to add.\n */\n function element(EVMFetchRequest memory request, bytes32 el) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n _addOperation(request, _addConstant(request, abi.encode(el)));\n return request;\n }\n\n /**\n * @dev Adds an `address` element to the current path.\n * @param request The request object being operated on.\n * @param el The element to add.\n */\n function element(EVMFetchRequest memory request, address el) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n _addOperation(request, _addConstant(request, abi.encode(el)));\n return request;\n }\n\n /**\n * @dev Adds a `bytes` element to the current path.\n * @param request The request object being operated on.\n * @param el The element to add.\n */\n function element(EVMFetchRequest memory request, bytes memory el) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n _addOperation(request, _addConstant(request, el));\n return request;\n }\n\n /**\n * @dev Adds a `string` element to the current path.\n * @param request The request object being operated on.\n * @param el The element to add.\n */\n function element(EVMFetchRequest memory request, string memory el) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n _addOperation(request, _addConstant(request, bytes(el)));\n return request;\n }\n\n /**\n * @dev Adds a reference to a previous fetch to the current path.\n * @param request The request object being operated on.\n * @param idx The index of the previous fetch request, starting at 0.\n */\n function ref(EVMFetchRequest memory request, uint8 idx) internal pure returns (EVMFetchRequest memory) {\n if(request.operationIdx >= 32) {\n revert CommandTooLong();\n }\n if(idx > request.commands.length || idx > 31) {\n revert InvalidReference(idx, request.commands.length);\n }\n _addOperation(request, OP_BACKREF | idx);\n return request;\n }\n\n /**\n * @dev Initiates the fetch request.\n * Calling this function terminates execution; clients that implement CCIP-Read will make a callback to\n * `callback` with the results of the operation.\n * @param callbackId A callback function selector on this contract that will be invoked via CCIP-Read with the result of the lookup.\n * The function must have a signature matching `(bytes[] memory values, bytes callbackData)` with a return type matching the call in which\n * this function was invoked. Its return data will be returned as the return value of the entire CCIP-read operation.\n * @param callbackData Extra data to supply to the callback.\n */\n function fetch(EVMFetchRequest memory request, bytes4 callbackId, bytes memory callbackData) internal view {\n if(request.commands.length > 0 && request.operationIdx < 32) {\n // Terminate last command\n _addOperation(request, OP_END);\n }\n revert OffchainLookup(\n address(this),\n request.verifier.gatewayURLs(),\n abi.encodeCall(IEVMGateway.getStorageSlots, (request.target, request.commands, request.constants)),\n EVMFetchTarget.getStorageSlotsCallback.selector,\n abi.encode(request.verifier, request.target, request.commands, request.constants, callbackId, callbackData)\n );\n }\n\n function _addConstant(EVMFetchRequest memory request, bytes memory value) private pure returns(uint8 idx) {\n bytes[] memory constants = request.constants;\n idx = uint8(constants.length);\n assembly {\n mstore(constants, add(idx, 1)) // Increment constant array length\n }\n constants[idx] = value;\n }\n\n function _addOperation(EVMFetchRequest memory request, uint8 op) private pure {\n uint256 commandIdx = request.commands.length - 1;\n request.commands[commandIdx] = request.commands[commandIdx] | (bytes32(bytes1(op)) >> (8 * request.operationIdx++));\n }\n}\n" + }, + "@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from './IEVMVerifier.sol';\nimport { Address } from '@openzeppelin/contracts/utils/Address.sol';\n\n/**\n * @dev Callback implementation for users of `EVMFetcher`. If you use `EVMFetcher`, your contract must\n * inherit from this contract in order to handle callbacks correctly.\n */\nabstract contract EVMFetchTarget {\n using Address for address;\n\n error ResponseLengthMismatch(uint256 actual, uint256 expected);\n\n /**\n * @dev Internal callback function invoked by CCIP-Read in response to a `getStorageSlots` request.\n */\n function getStorageSlotsCallback(bytes calldata response, bytes calldata extradata) external {\n bytes memory proof = abi.decode(response, (bytes));\n (IEVMVerifier verifier, address addr, bytes32[] memory commands, bytes[] memory constants, bytes4 callback, bytes memory callbackData) =\n abi.decode(extradata, (IEVMVerifier, address, bytes32[], bytes[], bytes4, bytes));\n bytes[] memory values = verifier.getStorageValues(addr, commands, constants, proof);\n if(values.length != commands.length) {\n revert ResponseLengthMismatch(values.length, commands.length);\n }\n bytes memory ret = address(this).functionCall(abi.encodeWithSelector(callback, values, callbackData));\n assembly {\n return(add(ret, 32), mload(ret))\n }\n }\n}\n" + }, + "@ensdomains/evm-verifier/contracts/EVMProofHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport {RLPReader} from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport {Bytes} from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport {SecureMerkleTrie} from \"./SecureMerkleTrie.sol\";\n\nstruct StateProof {\n bytes[] stateTrieWitness; // Witness proving the `storageRoot` against a state root.\n bytes[][] storageProofs; // An array of proofs of individual storage elements \n}\n\nuint8 constant OP_CONSTANT = 0x00;\nuint8 constant OP_BACKREF = 0x20;\nuint8 constant FLAG_DYNAMIC = 0x01;\n\nlibrary EVMProofHelper {\n using Bytes for bytes;\n\n error AccountNotFound(address);\n error UnknownOpcode(uint8);\n error InvalidSlotSize(uint256 size);\n\n /**\n * @notice Get the storage root for the provided merkle proof\n * @param stateRoot The state root the witness was generated against\n * @param target The address we are fetching a storage root for\n * @param witness A witness proving the value of the storage root for `target`.\n * @return The storage root retrieved from the provided state root\n */\n function getStorageRoot(bytes32 stateRoot, address target, bytes[] memory witness) private pure returns (bytes32) {\n (bool exists, bytes memory encodedResolverAccount) = SecureMerkleTrie.get(\n abi.encodePacked(target),\n witness,\n stateRoot\n );\n if(!exists) {\n revert AccountNotFound(target);\n }\n RLPReader.RLPItem[] memory accountState = RLPReader.readList(encodedResolverAccount);\n return bytes32(RLPReader.readBytes(accountState[2]));\n }\n\n /**\n * @notice Prove whether the provided storage slot is part of the storageRoot\n * @param storageRoot the storage root for the account that contains the storage slot\n * @param slot The storage key we are fetching the value of\n * @param witness the StorageProof struct containing the necessary proof data\n * @return The retrieved storage proof value or 0x if the storage slot is empty\n */\n function getSingleStorageProof(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns (bytes memory) {\n (bool exists, bytes memory retrievedValue) = SecureMerkleTrie.get(\n abi.encodePacked(slot),\n witness,\n storageRoot\n );\n if(!exists) {\n // Nonexistent values are treated as zero.\n return \"\";\n }\n return RLPReader.readBytes(retrievedValue);\n }\n\n function getFixedValue(bytes32 storageRoot, uint256 slot, bytes[] memory witness) private pure returns(bytes32) {\n bytes memory value = getSingleStorageProof(storageRoot, slot, witness);\n // RLP encoded storage slots are stored without leading 0 bytes.\n // Casting to bytes32 appends trailing 0 bytes, so we have to bit shift to get the \n // original fixed-length representation back.\n return bytes32(value) >> (256 - 8 * value.length);\n }\n\n function executeOperation(bytes1 operation, bytes[] memory constants, bytes[] memory values) private pure returns(bytes memory) {\n uint8 opcode = uint8(operation) & 0xe0;\n uint8 operand = uint8(operation) & 0x1f;\n\n if(opcode == OP_CONSTANT) {\n return constants[operand];\n } else if(opcode == OP_BACKREF) {\n return values[operand];\n } else {\n revert UnknownOpcode(opcode);\n }\n }\n\n function computeFirstSlot(bytes32 command, bytes[] memory constants, bytes[] memory values) private pure returns(bool isDynamic, uint256 slot) {\n uint8 flags = uint8(command[0]);\n isDynamic = (flags & FLAG_DYNAMIC) != 0;\n\n bytes memory slotData = executeOperation(command[1], constants, values);\n require(slotData.length == 32, \"First path element must be 32 bytes\");\n slot = uint256(bytes32(slotData));\n\n for(uint256 j = 2; j < 32 && command[j] != 0xff; j++) {\n bytes memory index = executeOperation(command[j], constants, values);\n slot = uint256(keccak256(abi.encodePacked(index, slot)));\n }\n }\n\n function getDynamicValue(bytes32 storageRoot, uint256 slot, StateProof memory proof, uint256 proofIdx) private pure returns(bytes memory value, uint256 newProofIdx) {\n uint256 firstValue = uint256(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n if(firstValue & 0x01 == 0x01) {\n // Long value: first slot is `length * 2 + 1`, following slots are data.\n uint256 length = (firstValue - 1) / 2;\n value = \"\";\n slot = uint256(keccak256(abi.encodePacked(slot)));\n // This is horribly inefficient - O(n^2). A better approach would be to build an array of words and concatenate them\n // all at once, but we're trying to avoid writing new library code.\n while(length > 0) {\n if(length < 32) {\n value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]).slice(0, length));\n length = 0;\n } else {\n value = bytes.concat(value, getSingleStorageProof(storageRoot, slot++, proof.storageProofs[proofIdx++]));\n length -= 32;\n }\n }\n return (value, proofIdx);\n } else {\n // Short value: least significant byte is `length * 2`, other bytes are data.\n uint256 length = (firstValue & 0xFF) / 2;\n return (abi.encode(firstValue).slice(0, length), proofIdx);\n }\n }\n\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes32 stateRoot, StateProof memory proof) internal pure returns(bytes[] memory values) {\n bytes32 storageRoot = getStorageRoot(stateRoot, target, proof.stateTrieWitness);\n uint256 proofIdx = 0;\n values = new bytes[](commands.length);\n for(uint256 i = 0; i < commands.length; i++) {\n bytes32 command = commands[i];\n (bool isDynamic, uint256 slot) = computeFirstSlot(command, constants, values);\n if(!isDynamic) {\n values[i] = abi.encode(getFixedValue(storageRoot, slot, proof.storageProofs[proofIdx++]));\n if(values[i].length > 32) {\n revert InvalidSlotSize(values[i].length);\n }\n } else {\n (values[i], proofIdx) = getDynamicValue(storageRoot, slot, proof, proofIdx);\n }\n }\n }\n}" + }, + "@ensdomains/evm-verifier/contracts/IEVMVerifier.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\ninterface IEVMVerifier {\n function gatewayURLs() external view returns(string[] memory);\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values);\n}\n" + }, + "@ensdomains/evm-verifier/contracts/MerkleTrie.sol": { + "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n// as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n// in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\n\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice RLP representation of `NULL`.\n */\n bytes internal constant RLP_NULL = hex\"80\";\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n (bool exists, bytes memory value) = get(_key, _proof, _root);\n return (exists && Bytes.equal(_value, value));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Whether or not the key exists.\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool, bytes memory) {\n TrieNode[] memory proof = _parseProof(_proof);\n (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(\n proof,\n _key,\n _root\n );\n\n bool noRemainder = keyRemainder.length == 0;\n\n require(noRemainder || isFinalNode, \"MerkleTrie: provided proof is invalid\");\n\n bytes memory value = noRemainder ? _getNodeValue(proof[pathLength - 1]) : bytes(\"\");\n\n return (value.length > 0, value);\n }\n\n /**\n * @notice Walks through a proof using a provided key.\n *\n * @param _proof Inclusion proof to walk through.\n * @param _key Key to use for the walk.\n * @param _root Known root of the trie.\n *\n * @return Length of the final path\n * @return Portion of the key remaining after the walk.\n * @return Whether or not we've hit a dead end.\n */\n // solhint-disable-next-line code-complexity\n function _walkNodePath(\n TrieNode[] memory _proof,\n bytes memory _key,\n bytes32 _root\n )\n private\n pure\n returns (\n uint256,\n bytes memory,\n bool\n )\n {\n uint256 pathLength = 0;\n bytes memory key = Bytes.toNibbles(_key);\n\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n uint256 currentKeyIncrement = 0;\n TrieNode memory currentNode;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < _proof.length; i++) {\n currentNode = _proof[i];\n currentKeyIndex += currentKeyIncrement;\n\n // Keep track of the proof elements we actually need.\n // It's expensive to resize arrays, so this simply reduces gas costs.\n pathLength += 1;\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // We've hit the end of the key\n // meaning the value should be within this branch node.\n break;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIncrement = 1;\n continue;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n require(\n keyRemainder.length >= pathRemainder.length,\n \"MerkleTrie: invalid key length for leaf or extension node\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n if (\n pathRemainder.length == sharedNibbleLength &&\n keyRemainder.length == sharedNibbleLength\n ) {\n // The key within this leaf matches our key exactly.\n // Increment the key index to reflect that we have no remainder.\n currentKeyIndex += sharedNibbleLength;\n }\n\n // We've hit a leaf node, so our next node should be NULL.\n currentNodeID = RLP_NULL;\n break;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n if (sharedNibbleLength != pathRemainder.length) {\n // Our extension node is not identical to the remainder.\n // We've hit the end of this path\n // updates will need to modify this extension.\n currentNodeID = RLP_NULL;\n break;\n } else {\n // Our extension shares some nibbles.\n // Carry on to the next node.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIncrement = sharedNibbleLength;\n continue;\n }\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n return (\n pathLength,\n Bytes.slice(key, currentKeyIndex),\n Bytes.equal(currentNodeID, RLP_NULL)\n );\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Gets the value for a node.\n *\n * @param _node Node to get a value for.\n *\n * @return Node value, as hex bytes.\n */\n function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {\n return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}" + }, + "@ensdomains/evm-verifier/contracts/SecureMerkleTrie.sol": { + "content": "// Pulled from https://github.com/ethereum-optimism/optimism/blob/4d13f0afe8869faf7bba45d8339998525ebc5161/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol\n// as this is the last version of Optimism's Merkle Trie library that supports nonexistence proofs; support was removed\n// in the next commit for some version.\n// Copyright 2020-2021 Optimism\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Whether or not the key exists.\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool, bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}" + }, + "@ensdomains/l1-verifier/contracts/L1Verifier.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IEVMVerifier } from \"@ensdomains/evm-verifier/contracts/IEVMVerifier.sol\";\nimport { RLPReader } from \"@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol\";\nimport { StateProof, EVMProofHelper } from \"@ensdomains/evm-verifier/contracts/EVMProofHelper.sol\";\n\nstruct L1WitnessData {\n uint256 blockNo;\n bytes blockHeader;\n}\n\ncontract L1Verifier is IEVMVerifier {\n error BlockHeaderHashMismatch(uint256 current, uint256 number, bytes32 expected, bytes32 actual);\n\n string[] _gatewayURLs;\n\n constructor(string[] memory urls) {\n _gatewayURLs = urls;\n }\n\n function gatewayURLs() external view returns(string[] memory) {\n return _gatewayURLs;\n }\n\n function getStorageValues(address target, bytes32[] memory commands, bytes[] memory constants, bytes memory proof) external view returns(bytes[] memory values) {\n (L1WitnessData memory l1Data, StateProof memory stateProof) = abi.decode(proof, (L1WitnessData, StateProof));\n if(keccak256(l1Data.blockHeader) != blockhash(l1Data.blockNo)) {\n revert BlockHeaderHashMismatch(block.number, l1Data.blockNo, blockhash(l1Data.blockNo), keccak256(l1Data.blockHeader));\n }\n RLPReader.RLPItem[] memory headerFields = RLPReader.readList(l1Data.blockHeader);\n bytes32 stateRoot = bytes32(RLPReader.readBytes(headerFields[3]));\n return EVMProofHelper.getStorageValues(target, commands, constants, stateRoot, stateProof);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/src/libraries/Bytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Bytes\n/// @notice Bytes is a library for manipulating byte arrays.\nlibrary Bytes {\n /// @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n /// @notice Slices a byte array with a given starting index and length. Returns a new byte array\n /// as opposed to a pointer to the original array. Will throw if trying to slice more\n /// bytes than exist in the array.\n /// @param _bytes Byte array to slice.\n /// @param _start Starting index of the slice.\n /// @param _length Length of the slice.\n /// @return Slice of the input byte array.\n function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } { mstore(mc, mload(cc)) }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /// @notice Slices a byte array with a given starting index up to the end of the original byte\n /// array. Returns a new array rathern than a pointer to the original.\n /// @param _bytes Byte array to slice.\n /// @param _start Starting index of the slice.\n /// @return Slice of the input byte array.\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /// @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n /// Resulting nibble array will be exactly twice as long as the input byte array.\n /// @param _bytes Input byte array to convert.\n /// @return Resulting nibble array.\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n bytes memory _nibbles;\n assembly {\n // Grab a free memory offset for the new array\n _nibbles := mload(0x40)\n\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Calculate the length of the new nibble array\n // This is the length of the input array times 2\n let nibblesLength := shl(0x01, bytesLength)\n\n // Update the free memory pointer to allocate memory for the new array.\n // To do this, we add the length of the new array + 32 bytes for the array length\n // rounded up to the nearest 32 byte boundary to the current free memory pointer.\n mstore(0x40, add(_nibbles, and(not(0x1F), add(nibblesLength, 0x3F))))\n\n // Store the length of the new array in memory\n mstore(_nibbles, nibblesLength)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(_nibbles, 0x20)\n\n // Loop through each byte in the input array\n for { let i := 0x00 } lt(i, bytesLength) { i := add(i, 0x01) } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n return _nibbles;\n }\n\n /// @notice Compares two byte arrays by comparing their keccak256 hashes.\n /// @param _bytes First byte array to compare.\n /// @param _other Second byte array to compare.\n /// @return True if the two byte arrays are equal, false otherwise.\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" + }, + "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/// @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n/// @title RLPReader\n/// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n/// from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n/// various tweaks to improve readability.\nlibrary RLPReader {\n /// @notice Custom pointer type to avoid confusion between pointers and uint256s.\n type MemoryPointer is uint256;\n\n /// @notice RLP item types.\n /// @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n /// @custom:value LIST_ITEM Represents an RLP list item.\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /// @notice Struct representing an RLP item.\n /// @custom:field length Length of the RLP item.\n /// @custom:field ptr Pointer to the RLP item in memory.\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /// @notice Max list length that this library will accept.\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /// @notice Converts bytes to a reference to memory position and length.\n /// @param _in Input bytes to convert.\n /// @return out_ Output memory reference.\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) {\n // Empty arrays are not RLP items.\n require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n out_ = RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /// @notice Reads an RLP list value into a list of RLP items.\n /// @param _in RLP list value.\n /// @return out_ Decoded RLP list items.\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(itemType == RLPItemType.LIST_ITEM, \"RLPReader: decoded item type for list is not a list item\");\n\n require(listOffset + listLength == _in.length, \"RLPReader: list item has an invalid data remainder\");\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n out_ = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength,) = _decodeLength(\n RLPItem({ length: _in.length - offset, ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out_[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out_, itemCount)\n }\n }\n\n /// @notice Reads an RLP list value into a list of RLP items.\n /// @param _in RLP list value.\n /// @return out_ Decoded RLP list items.\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) {\n out_ = readList(toRLPItem(_in));\n }\n\n /// @notice Reads an RLP bytes value into bytes.\n /// @param _in RLP bytes value.\n /// @return out_ Decoded bytes.\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(itemType == RLPItemType.DATA_ITEM, \"RLPReader: decoded item type for bytes is not a data item\");\n\n require(_in.length == itemOffset + itemLength, \"RLPReader: bytes value contains an invalid remainder\");\n\n out_ = _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /// @notice Reads an RLP bytes value into bytes.\n /// @param _in RLP bytes value.\n /// @return out_ Decoded bytes.\n function readBytes(bytes memory _in) internal pure returns (bytes memory out_) {\n out_ = readBytes(toRLPItem(_in));\n }\n\n /// @notice Reads the raw bytes of an RLP item.\n /// @param _in RLP item to read.\n /// @return out_ Raw RLP bytes.\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {\n out_ = _copy(_in.ptr, 0, _in.length);\n }\n\n /// @notice Decodes the length of an RLP item.\n /// @param _in RLP item to decode.\n /// @return offset_ Offset of the encoded data.\n /// @return length_ Length of the encoded data.\n /// @return type_ RLP item type (LIST_ITEM or DATA_ITEM).\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (uint256 offset_, uint256 length_, RLPItemType type_)\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(_in.length > 0, \"RLPReader: length of an RLP item must be greater than zero to be decodable\");\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen, \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(strLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long string)\");\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(_in.length > listLen, \"RLPReader: length of content must be greater than list length (short list)\");\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00, \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(listLen > 55, \"RLPReader: length of content must be greater than 55 bytes (long list)\");\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /// @notice Copies the bytes from a memory location.\n /// @param _src Pointer to the location to read from.\n /// @param _offset Offset to start reading from.\n /// @param _length Number of bytes to read.\n /// @return out_ Copied bytes.\n function _copy(MemoryPointer _src, uint256 _offset, uint256 _length) private pure returns (bytes memory out_) {\n out_ = new bytes(_length);\n if (_length == 0) {\n return out_;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out_, 32)\n let i := 0\n for { } lt(i, _length) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) }\n\n if gt(i, _length) { mstore(add(dest, _length), 0) }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../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 * By default, the owner account will be the one that deploys the contract. This\n * can 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 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\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 require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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 require(newOwner != address(0), \"Ownable: new owner is the zero address\");\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 v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\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 *\n * _Available since v4.1._\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/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n * function (like regular Solidity function calls).\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 * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\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 * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n return\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n isValidERC1271SignatureNow(signer, hash, signature);\n }\n\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n * against the signer smart contract using ERC1271.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidERC1271SignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length >= 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@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" + }, + "@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 // → `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 + (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" + }, + "@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" + }, + "@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" + }, + "contracts/DefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\nimport \"./IDefaultReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/reverseRegistrar/SignatureReverseResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/wrapper/BytesUtils.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * A fallback reverser resolver to resolve when L2 reverse resolver has no names set.\n * The contract will be set under \"default.reverse\" namespace\n * It can only be set by EOA as contract accounts are chain dependent.\n */\ncontract DefaultReverseResolver is\n Ownable,\n IDefaultReverseResolver,\n ERC165,\n SignatureReverseResolver\n{\n using ECDSA for bytes32;\n using BytesUtils for bytes;\n // The namehash of 'default.reverse'\n bytes32 private constant DEFAULT_REVERSE_NODE =\n 0x53a2e7cce84726721578c676b4798972d354dd7c62c832415371716693edd312;\n\n /**\n * @dev Constructor\n */\n constructor() SignatureReverseResolver(DEFAULT_REVERSE_NODE, 0) {}\n\n function isAuthorised(address addr) internal view override returns (bool) {\n if (addr != msg.sender) {\n revert Unauthorised();\n }\n }\n\n /*\n * Returns the name associated with an address, for reverse records.\n * This function is non ENSIP standard\n * @param address The ENS address to query.\n * @return The associated name.\n */\n function name(address addr) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_names[recordVersions[node]][node];\n }\n\n /*\n * Returns the text data associated with an address and key.\n * @param address The ENS address to query.\n * @param key The text data key to query.\n * @return The associated text data.\n */\n function text(\n address addr,\n string memory key\n ) public view returns (string memory) {\n bytes32 node = _getNamehash(addr);\n return versionable_texts[recordVersions[node]][node][key];\n }\n\n function supportsInterface(\n bytes4 interfaceID\n ) public view override(ERC165, SignatureReverseResolver) returns (bool) {\n return\n interfaceID == type(IDefaultReverseResolver).interfaceId ||\n super.supportsInterface(interfaceID);\n }\n}\n" + }, + "contracts/deps.sol": { + "content": "import {L1Verifier} from '@ensdomains/l1-verifier/contracts/L1Verifier.sol';\nimport '@ensdomains/ens-contracts/contracts/reverseRegistrar/L2ReverseRegistrar.sol';\nimport '@ensdomains/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol';\n// Storage slot\n// ┌────────────────────┬───────────────────┬──────────────┬\n// │ contract │ state_variable │ storage_slot │\n// ├────────────────────┼───────────────────┼──────────────┼\n// │ L2ReverseRegistrar │ _owner │ 0 │\n// │ L2ReverseRegistrar │ lastUpdated │ 1 │\n// │ L2ReverseRegistrar │ versionable_texts │ 2 │\n// │ L2ReverseRegistrar │ versionable_names │ 3 │\n// │ L2ReverseRegistrar │ recordVersions │ 4 │\n" + }, + "contracts/IDefaultReverseResolver.sol": { + "content": "pragma solidity >=0.8.4;\n\ninterface IDefaultReverseResolver {\n function name(address addr) external view returns (string memory);\n\n function text(\n address addr,\n string memory key\n ) external view returns (string memory);\n}\n" + }, + "contracts/L1ReverseResolver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol';\nimport {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol';\nimport {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol';\nimport \"@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\";\nimport \"@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport \"@ensdomains/ens-contracts/contracts/utils/HexUtils.sol\";\nimport \"@ensdomains/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\";\nimport \"./IDefaultReverseResolver.sol\";\n\ncontract L1ReverseResolver is EVMFetchTarget, IExtendedResolver, ERC165 {\n using EVMFetcher for EVMFetcher.EVMFetchRequest;\n IEVMVerifier immutable verifier;\n address immutable target;\n IDefaultReverseResolver immutable defaultReverseResolver;\n uint256 constant VERSIONABLE_TEXTS_SLOT = 2;\n uint256 constant VERSIONABLE_NAME_SLOT = 3;\n uint256 constant RECORD_VERSIONS_SLOT = 4;\n uint256 constant ADDRESS_LENGTH = 40;\n using HexUtils for bytes;\n\n constructor(IEVMVerifier _verifier, address _target, IDefaultReverseResolver _defaultReverseResolver ) {\n verifier = _verifier;\n target = _target;\n defaultReverseResolver = _defaultReverseResolver;\n }\n\n /** \n * @dev Resolve and verify a record stored in l2 target address. It supports fallback to the default resolver\n * @param name DNS encoded ENS name to query\n * @param data The actual calldata\n * @return result result of the call\n */\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory result) {\n bytes4 selector = bytes4(data);\n (address addr,) = HexUtils.hexToAddress(name, 1, ADDRESS_LENGTH + 1);\n if (selector == INameResolver.name.selector) {\n (bytes32 node) = abi.decode(data[4:], (bytes32));\n return bytes(_name(node, addr));\n }\n if (selector == ITextResolver.text.selector) {\n (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string));\n return bytes(_text(node, key, addr));\n }\n }\n\n function _name(bytes32 node, address addr) private view returns (string memory) {\n EVMFetcher.newFetchRequest(verifier, target)\n .getStatic(RECORD_VERSIONS_SLOT)\n .element(node)\n .getDynamic(VERSIONABLE_NAME_SLOT)\n .ref(0)\n .element(node)\n .fetch(this.nameCallback.selector, abi.encode(addr));\n }\n\n function nameCallback(\n bytes[] memory values,\n bytes memory callbackdata\n ) public view returns (string memory) { \n if(values[1].length == 0 ){\n (address addr) = abi.decode(callbackdata, (address));\n return defaultReverseResolver.name(addr);\n }else{\n return string(values[1]);\n }\n }\n\n function _text(\n bytes32 node,\n string memory key,\n address addr\n ) private view returns (string memory) {\n EVMFetcher.newFetchRequest(verifier, target)\n .getStatic(RECORD_VERSIONS_SLOT)\n .element(node)\n .getDynamic(VERSIONABLE_TEXTS_SLOT)\n .ref(0)\n .element(node)\n .element(key)\n .fetch(this.textCallback.selector, abi.encode(addr, key));\n }\n\n function textCallback(\n bytes[] memory values,\n bytes memory callbackdata\n ) public view returns (string memory) {\n if(values[1].length == 0 ){\n (address addr, string memory key) = abi.decode(callbackdata, (address, string));\n return defaultReverseResolver.text(addr, key);\n }else{\n return string(values[1]);\n }\n }\n\n function supportsInterface(\n bytes4 interfaceId\n ) public override view returns (bool) {\n return\n interfaceId == type(IExtendedResolver).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "storageLayout" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/crosschain-reverse-resolver/package.json b/crosschain-reverse-resolver/package.json index d129b092..5e7bc16c 100644 --- a/crosschain-reverse-resolver/package.json +++ b/crosschain-reverse-resolver/package.json @@ -7,6 +7,7 @@ "test": "node scripts/test.js", "storage": "hardhat check", "setname": "hardhat run scripts/setname.ts", + "setdefaultname": "hardhat run scripts/setdefaultname.ts --network sepolia", "getname": "hardhat run scripts/getname.ts --network sepolia", "clean": "rm -fr artifacts cache node_modules typechain-types", "lint": "exit 0" diff --git a/crosschain-reverse-resolver/scripts/getname.ts b/crosschain-reverse-resolver/scripts/getname.ts index c435fbfc..72dea1eb 100644 --- a/crosschain-reverse-resolver/scripts/getname.ts +++ b/crosschain-reverse-resolver/scripts/getname.ts @@ -1,16 +1,22 @@ import hre from 'hardhat'; import packet from 'dns-packet'; -const abi = ['function name(bytes32) view returns(string)']; +const abi = [ + 'function supportsInterface(bytes4) view returns(bool)', + 'function name(bytes32) view returns(string)', + 'function resolve(bytes,bytes) view returns(bytes)' +]; +const defaultabi = ['function name(address) view returns(string)']; const encodeName = (name) => '0x' + packet.name.encode(name).toString('hex') +const extendedResolverInterface = '0x9061b923' import {ethers} from 'ethers'; export const main = async () => { if (!process.env.REVERSE_NAMESPACE || !process.env.L1_PROVIDER_URL || !process.env.ETH_ADDRESS) throw 'Set REVERSE_NAMESPACE, L1_PROVIDER_URL and ETH_ADDRESS'; - const namespace = process.env.REVERSE_NAMESPACE; const L1_PROVIDER_URL = process.env.L1_PROVIDER_URL; const L2_PROVIDER_URL = process.env.L2_PROVIDER_URL; const L2_REVERSE_REGISTRAR_ADDRESS = process.env.L2_REVERSE_REGISTRAR_ADDRESS + const DEFAULT_REVERSE_RESOLVER_ADDRESS = process.env.DEFAULT_REVERSE_RESOLVER_ADDRESS const ETH_ADDRESS = process.env.ETH_ADDRESS; const provider = new ethers.JsonRpcProvider(L1_PROVIDER_URL); const l2provider = new ethers.JsonRpcProvider(L2_PROVIDER_URL); @@ -20,13 +26,24 @@ export const main = async () => { console.log({namespace, ETH_ADDRESS, name, encodedname,reversenode}) const reverseresolver = await provider.getResolver(namespace); - console.log({reverseresolver}) + console.log({L2_PROVIDER_URL, L2_REVERSE_REGISTRAR_ADDRESS}) if (L2_PROVIDER_URL && L2_REVERSE_REGISTRAR_ADDRESS){ const l2resolver = new ethers.Contract(L2_REVERSE_REGISTRAR_ADDRESS, abi, l2provider); console.log(`l2: Reverse node for ${name} is set to `, await l2resolver.name(reversenode)) } + if(DEFAULT_REVERSE_RESOLVER_ADDRESS){ + const defaultResolver = new ethers.Contract(DEFAULT_REVERSE_RESOLVER_ADDRESS, defaultabi, provider); + } const l1resolver = new ethers.Contract(reverseresolver.address, abi, provider); - console.log(`l1: Reverse node for ${name} is set to `, await l1resolver.name(reversenode, {enableCcipRead:true})) + if(await l1resolver.supportsInterface(extendedResolverInterface)){ + const i = new ethers.Interface(abi) + const calldata = i.encodeFunctionData("name", [reversenode]) + const result = await l1resolver.resolve(encodedname, calldata, { enableCcipRead: true }) + console.log(`l1: Reverse node for ${name} is set to `, ethers.toUtf8String(result)) + }else { + const result = await l1resolver.name(reversenode, { enableCcipRead: true }) + console.log(`l1: Reverse node for ${name} is set to `, result) + } }; main(); \ No newline at end of file diff --git a/crosschain-reverse-resolver/scripts/setdefaultname.ts b/crosschain-reverse-resolver/scripts/setdefaultname.ts new file mode 100644 index 00000000..46b84261 --- /dev/null +++ b/crosschain-reverse-resolver/scripts/setdefaultname.ts @@ -0,0 +1,60 @@ +import hre from 'hardhat'; + +const ethers = hre.ethers; +export const main = async () => { + const [signer] = await hre.ethers.getSigners(); + if (!process.env.DEPLOYER_PRIVATE_KEY) + throw 'Set DEPLOYER_PRIVATE_KEY'; + if (!process.env.REVERSE_NAMESPACE) + throw 'Set REVERSE_NAMESPACE'; + if (!process.env.L1_PROVIDER_URL) + throw 'Set L1_PROVIDER_URL'; + if (!process.env.DEFAULT_REVERSE_RESOLVER_ADDRESS) + throw 'Set DEFAULT_REVERSE_RESOLVER_ADDRESS'; + if (!process.env.DEFAULT_ENS_NAME) + throw 'Set DEFAULT_ENS_NAME'; + const L1_PROVIDER_URL = process.env.L1_PROVIDER_URL; + const DEFAULT_REVERSE_RESOLVER_ADDRESS = process.env.DEFAULT_REVERSE_RESOLVER_ADDRESS; + const DEPLOYER_PRIVATE_KEY = process.env.DEPLOYER_PRIVATE_KEY; + const namespace = process.env.REVERSE_NAMESPACE; + const DEFAULT_ENS_NAME = process.env.DEFAULT_ENS_NAME; + const DefaultReverseResolverFactory = (await hre.ethers.getContractFactory("DefaultReverseResolver")) as DefaultReverseResolverFactory__factory; + const DefaultReverseResolver = DefaultReverseResolverFactory + .connect(signer) + .attach(DEFAULT_REVERSE_RESOLVER_ADDRESS); + const testSigner = new ethers.Wallet(DEPLOYER_PRIVATE_KEY); + const ETH_ADDRESS = testSigner.address + const name = ETH_ADDRESS.substring(2).toLowerCase() + "." + namespace + const reversenode = ethers.namehash(name) + console.log({ DEFAULT_REVERSE_RESOLVER_ADDRESS, L1_PROVIDER_URL,DEFAULT_ENS_NAME, ETH_ADDRESS, namespace, name, reversenode}) + + const funcId = ethers + .id('setNameForAddrWithSignature(address,string,uint256,bytes)') + .substring(0, 10) + const block = await ethers.provider.getBlock("latest") + const inceptionDate = block?.timestamp + const message = ethers.solidityPackedKeccak256( + ['bytes32', 'address', 'uint256', 'uint256'], + [ethers.solidityPackedKeccak256(['bytes4', 'string'], [funcId, DEFAULT_ENS_NAME]), ETH_ADDRESS, inceptionDate, 0], + ) + const signature = await testSigner.signMessage(ethers.toBeArray(message)) + console.log({ + ETH_ADDRESS, + DEFAULT_ENS_NAME, + inceptionDate, + signature + }) + + const tx = await DefaultReverseResolver['setNameForAddrWithSignature']( + ETH_ADDRESS, + DEFAULT_ENS_NAME, + inceptionDate, + signature, + ) + + const rec = await tx.wait(); + console.log({txhash:rec.hash}); + console.log(await DefaultReverseResolver.name(ETH_ADDRESS)) +}; + +main(); \ No newline at end of file diff --git a/crosschain-reverse-resolver/scripts/setname.ts b/crosschain-reverse-resolver/scripts/setname.ts index 05896d88..248c747f 100644 --- a/crosschain-reverse-resolver/scripts/setname.ts +++ b/crosschain-reverse-resolver/scripts/setname.ts @@ -20,16 +20,16 @@ export const main = async () => { const name = ETH_ADDRESS.substring(2).toLowerCase() + "." + namespace const reversenode = ethers.namehash(name) - const L2ReverseRegistrarFactory = (await hre.ethers.getContractFactory("L2ReverseRegistrar")) as L2ReverseRegistrarFactory__factory; - const l2ReverseRegistrar = L2ReverseRegistrarFactory + const L2ReverseResolverFactory = (await hre.ethers.getContractFactory("L2ReverseResolver")) as L2ReverseResolverFactory__factory; + const L2ReverseResolver = L2ReverseResolverFactory .connect(signer) .attach(L2_REVERSE_REGISTRAR_ADDRESS); console.log({ L2_REVERSE_REGISTRAR_ADDRESS, L2_PROVIDER_URL,ENS_NAME, ETH_ADDRESS, namespace, name, reversenode}) - const tx = await l2ReverseRegistrar.setName(ENS_NAME); + const tx = await L2ReverseResolver.setName(ENS_NAME); const rec = await tx.wait(); console.log({txhash:rec.hash}); - console.log(await l2ReverseRegistrar.name(reversenode)) + console.log(await L2ReverseResolver.name(reversenode)) }; main(); \ No newline at end of file diff --git a/crosschain-reverse-resolver/test/testReverseResolver.ts b/crosschain-reverse-resolver/test/testReverseResolver.ts index ede07790..ce4e1ebe 100644 --- a/crosschain-reverse-resolver/test/testReverseResolver.ts +++ b/crosschain-reverse-resolver/test/testReverseResolver.ts @@ -14,7 +14,10 @@ import { FetchRequest } from 'ethers'; import { ethers } from 'hardhat'; import { EthereumProvider } from 'hardhat/types'; import request from 'supertest'; +import packet from 'dns-packet'; const NAMESPACE = 2147483658 // OP +const encodeName = (name) => '0x' + packet.name.encode(name).toString('hex') + type ethersObj = typeof ethersT & Omit & { provider: Omit & { @@ -29,12 +32,22 @@ declare module 'hardhat/types/runtime' { } } +// looks like there are time dependencies for verification to success, hence adding a dalay +const wait = async x => { + return new Promise(resolve => { + setTimeout(resolve, 3000, 2 * x); + }); +}; + describe('Crosschain Reverse Resolver', () => { let provider: BrowserProvider; let signer: Signer; let verifier: Contract; let target: Contract; let l2contract: Contract; + let l2contractAddress: string; + let defaultReverseResolver: Contract; + let defaultReverseAddress: string; before(async () => { // Hack to get a 'real' ethers provider from hardhat. The default `HardhatProvider` @@ -71,52 +84,173 @@ describe('Crosschain Reverse Resolver', () => { signer ); verifier = await l1VerifierFactory.deploy(['test:']); - + const DefaultReverseResolverFactory = await ethers.getContractFactory( + 'DefaultReverseResolver', + ) + defaultReverseResolver = await DefaultReverseResolverFactory.deploy() + await provider.send('evm_mine', []); const testL2Factory = await ethers.getContractFactory( - 'L2ReverseRegistrar', + 'L2ReverseResolver', signer ); l2contract = await testL2Factory.deploy(ethers.namehash(`${NAMESPACE}.reverse`), NAMESPACE); - + l2contractAddress = await l2contract.getAddress(); + defaultReverseAddress = await defaultReverseResolver.getAddress(); const testL1Factory = await ethers.getContractFactory( 'L1ReverseResolver', signer ); - target = await testL1Factory.deploy(await verifier.getAddress(), await l2contract.getAddress()); + target = await testL1Factory.deploy( + await verifier.getAddress(), + l2contractAddress, + defaultReverseAddress + ); // Mine an empty block so we have something to prove against await provider.send('evm_mine', []); }); it("should test name", async() => { const name = 'vitalik.eth' + const testAddress = await signer.getAddress() const node = await l2contract.node( - await signer.getAddress(), + testAddress, ) - await l2contract.clearRecords(await signer.getAddress()) + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const encodedL2ReverseName = encodeName(l2ReverseName) + + await l2contract.clearRecords(await signer.getAddress()) await l2contract.setName(name) await provider.send("evm_mine", []); - const result2 = await target.name(node, { enableCcipRead: true }) - expect(result2).to.equal(name); + await wait(1); + + const i = new ethers.Interface(["function name(bytes32) returns(string)"]) + const calldata = i.encodeFunctionData("name", [node]) + const result2 = await target.resolve(encodedL2ReverseName, calldata, { enableCcipRead: true }) + // throws Error: invalid length for result data + // const decoded = i.decodeFunctionResult("name", result2) + expect(ethers.toUtf8String(result2)).to.equal(name); + }) + + it("should test fallback name", async() => { + const testSigner = new ethers.Wallet('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'); + const testAddress = testSigner.address + const name = 'myname.eth' + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const l2ReverseNode = ethers.namehash(l2ReverseName) + const encodedL2ReverseName = encodeName(l2ReverseName) + + const defaultReverseName = `${reverseLabel}.default.reverse` + const defaultReverseNode = ethers.namehash(defaultReverseName) + const encodedDefaultReverseName = encodeName(defaultReverseName) + + const funcId = ethers + .id('setNameForAddrWithSignature(address,string,uint256,bytes)') + .substring(0, 10) + + const block = await provider.getBlock('latest') + const inceptionDate = block?.timestamp + const message = ethers.solidityPackedKeccak256( + ['address', 'bytes32', 'address', 'uint256', 'uint256'], + [defaultReverseAddress, ethers.solidityPackedKeccak256(['bytes4', 'string'], [funcId, name]), testAddress, inceptionDate, 0], + ) + const signature = await testSigner.signMessage(ethers.toBeArray(message)) + await defaultReverseResolver['setNameForAddrWithSignature']( + testAddress, + name, + inceptionDate, + signature, + ) + await provider.send("evm_mine", []); + await wait(1); + + const i = new ethers.Interface(["function name(bytes32) returns(string)"]) + expect(await defaultReverseResolver['name(address)'](testAddress)).to.equal(name) + + const defaultcalldata = i.encodeFunctionData("name", [defaultReverseNode]) + const defaultResult = await defaultReverseResolver.resolve(encodedDefaultReverseName, defaultcalldata) + expect(ethers.toUtf8String(defaultResult)).to.equal(name); + + const l2calldata = i.encodeFunctionData("name", [l2ReverseNode]) + const result2 = await target.resolve(encodedL2ReverseName, l2calldata, { enableCcipRead: true }) + expect(ethers.toUtf8String(result2)).to.equal(name); }) it("should test text record", async() => { const key = 'name' const value = 'nick.eth' + const testAddress = await signer.getAddress() const node = await l2contract.node( - await signer.getAddress(), + testAddress ) + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const encodedL2ReverseName = encodeName(l2ReverseName) + await l2contract.clearRecords(await signer.getAddress()) await l2contract.setText(key, value) await provider.send("evm_mine", []); + await wait(1); + const result = await l2contract.text(node, key) expect(result).to.equal(value); - const result2 = await target.text(node, key, { enableCcipRead: true }) - expect(result2).to.equal(value); + const i = new ethers.Interface(["function text(bytes32, string) returns(string)"]) + const calldata = i.encodeFunctionData("text", [node, key]) + const result2 = await target.resolve(encodedL2ReverseName, calldata, { enableCcipRead: true }) + expect(ethers.toUtf8String(result2)).to.equal(value); + }) + + it("should test fallback text", async() => { + const testSigner = new ethers.Wallet('0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'); + const testAddress = testSigner.address + const key = 'name' + const value = 'myname.eth' + const reverseLabel = testAddress.substring(2).toLowerCase() + const l2ReverseName = `${reverseLabel}.${NAMESPACE}.reverse` + const l2ReverseNode = ethers.namehash(l2ReverseName) + const encodedL2ReverseName = encodeName(l2ReverseName) + + const defaultReverseName = `${reverseLabel}.default.reverse` + const defaultReverseNode = ethers.namehash(defaultReverseName) + const encodedDefaultReverseName = encodeName(defaultReverseName) + + const funcId = ethers + .id('setTextForAddrWithSignature(address,string,string,uint256,bytes)') + .substring(0, 10) + + const block = await provider.getBlock('latest') + const inceptionDate = block?.timestamp + const message = ethers.solidityPackedKeccak256( + ['address', 'bytes32', 'address', 'uint256', 'uint256'], + [defaultReverseAddress, ethers.solidityPackedKeccak256(['bytes4', 'string', 'string'], [funcId, key, value]), testAddress, inceptionDate, 0], + ) + const signature = await testSigner.signMessage(ethers.toBeArray(message)) + await defaultReverseResolver['setTextForAddrWithSignature']( + testAddress, + key, + value, + inceptionDate, + signature, + ) + await provider.send("evm_mine", []); + await wait(1); + + expect(await defaultReverseResolver["text(address,string)"](testAddress, key)).to.equal(value) + const i = new ethers.Interface(["function text(bytes32,string) returns(string)"]) + + const defaultcalldata = i.encodeFunctionData("text", [defaultReverseNode, key]) + const defaultResult = await defaultReverseResolver.resolve(encodedDefaultReverseName, defaultcalldata) + expect(ethers.toUtf8String(defaultResult)).to.equal(value); + + const calldata = i.encodeFunctionData("text", [l2ReverseNode, key]) + const result2 = await target.resolve(encodedL2ReverseName, calldata, { enableCcipRead: true }) + expect(ethers.toUtf8String(result2)).to.equal(value); }) it("should support interface", async() => { - expect(await target.supportsInterface('0x59d1d43c')).to.equal(true) // ITextResolver - expect(await target.supportsInterface('0x691f3431')).to.equal(true) // INameResolver + expect(await defaultReverseResolver.supportsInterface('0x9061b923')).to.equal(true) // IExtendedResolver + expect(await target.supportsInterface('0x9061b923')).to.equal(true) // IExtendedResolver expect(await target.supportsInterface('0x01ffc9a7')).to.equal(true) // ERC-165 support }) });