diff --git a/arb-gateway/package.json b/arb-gateway/package.json index b61ec7fa..5da95138 100644 --- a/arb-gateway/package.json +++ b/arb-gateway/package.json @@ -57,7 +57,7 @@ }, "dependencies": { "@chainlink/ccip-read-server": "^0.2.1", - "@ensdomains/evm-gateway": "^0.1.0", + "@ensdomains/evm-gateway": "workspace:*", "@ethereumjs/block": "^5.0.0", "@nomicfoundation/ethereumjs-block": "^5.0.2", "commander": "^11.0.0", diff --git a/arb-verifier/package.json b/arb-verifier/package.json index 02175715..be4eaecf 100644 --- a/arb-verifier/package.json +++ b/arb-verifier/package.json @@ -15,8 +15,8 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.0", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomicfoundation/hardhat-verify": "^1.0.0", - "@typechain/ethers-v6": "^0.4.0", - "@typechain/hardhat": "^8.0.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/express": "^4.17.18", "@types/mocha": ">=9.1.0", @@ -26,19 +26,19 @@ "express": "^4.18.2", "ganache": "^7.9.1", "hardhat": "^2.16.0", - "hardhat-deploy": "^0.11.43", + "hardhat-deploy": "^0.12.2", "hardhat-deploy-ethers": "^0.4.1", "hardhat-gas-reporter": "^1.0.8", "solidity-bytes-utils": "^0.8.0", "solidity-coverage": "^0.8.1", "supertest": "^6.3.3", "ts-node": "^10.9.1", - "typechain": "^8.2.0", + "typechain": "^8.3.2", "typescript": "^5.2.2" }, "dependencies": { "@arbitrum/nitro-contracts": "^1.1.0", - "@ensdomains/evm-verifier": "^0.1.0", + "@ensdomains/evm-verifier": "workspace:*", "dotenv": "^16.3.1" } } diff --git a/bun.lockb b/bun.lockb index 36b93ba3..4c76634a 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/crosschain-resolver/contracts/L1Resolver.sol b/crosschain-resolver/contracts/L1Resolver.sol index e166744c..1fa026e7 100644 --- a/crosschain-resolver/contracts/L1Resolver.sol +++ b/crosschain-resolver/contracts/L1Resolver.sol @@ -4,16 +4,23 @@ pragma solidity ^0.8.17; import {EVMFetcher} from '@ensdomains/evm-verifier/contracts/EVMFetcher.sol'; import {EVMFetchTarget} from '@ensdomains/evm-verifier/contracts/EVMFetchTarget.sol'; import {IEVMVerifier} from '@ensdomains/evm-verifier/contracts/IEVMVerifier.sol'; -import "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; -import {INameWrapper} from "@ensdomains/ens-contracts/contracts/wrapper/INameWrapper.sol"; -import {BytesUtils} from "@ensdomains/ens-contracts/contracts/dnssec-oracle/BytesUtils.sol"; -import {IAddrResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol"; -import {IAddressResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol"; -import {ITextResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol"; -import {IContentHashResolver} from "@ensdomains/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol"; +import '@ensdomains/ens-contracts/contracts/registry/ENS.sol'; +import {INameWrapper} from '@ensdomains/ens-contracts/contracts/wrapper/INameWrapper.sol'; +import {BytesUtils} from '@ensdomains/ens-contracts/contracts/dnssec-oracle/BytesUtils.sol'; +import {IAddrResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol'; +import {IAddressResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol'; +import {ITextResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol'; +import {IContentHashResolver} from '@ensdomains/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol'; +import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; - -contract L1Resolver is EVMFetchTarget { +contract L1Resolver is + EVMFetchTarget, + IAddrResolver, + IAddressResolver, + ITextResolver, + IContentHashResolver, + IERC165 +{ using EVMFetcher for EVMFetcher.EVMFetchRequest; using BytesUtils for bytes; IEVMVerifier immutable verifier; @@ -36,7 +43,7 @@ contract L1Resolver is EVMFetchTarget { // isApprovedFor address owner = ens.owner(node); if (owner == address(nameWrapper)) { - owner = nameWrapper.ownerOf(uint256(node)); + owner = nameWrapper.ownerOf(uint256(node)); } return owner == msg.sender; } @@ -46,17 +53,19 @@ contract L1Resolver is EVMFetchTarget { _; } - constructor( - IEVMVerifier _verifier, - ENS _ens, - INameWrapper _nameWrapper - ){ - require(address(_nameWrapper) != address(0), "Name Wrapper address must be set"); - require(address(_verifier) != address(0), "Verifier address must be set"); - require(address(_ens) != address(0), "Registry address must be set"); - verifier = _verifier; - ens = _ens; - nameWrapper = _nameWrapper; + constructor(IEVMVerifier _verifier, ENS _ens, INameWrapper _nameWrapper) { + require( + address(_nameWrapper) != address(0), + 'Name Wrapper address must be set' + ); + require( + address(_verifier) != address(0), + 'Verifier address must be set' + ); + require(address(_ens) != address(0), 'Registry address must be set'); + verifier = _verifier; + ens = _ens; + nameWrapper = _nameWrapper; } /** @@ -64,9 +73,9 @@ contract L1Resolver is EVMFetchTarget { * @param node The ENS node to query. * @param target The L2 resolver address to verify against. */ - function setTarget(bytes32 node, address target) public authorised(node){ - targets[node] = target; - emit TargetSet(node, target); + function setTarget(bytes32 node, address target) public authorised(node) { + targets[node] = target; + emit TargetSet(node, target); } /** @@ -84,70 +93,83 @@ contract L1Resolver is EVMFetchTarget { node = bytes32(0); if (len > 0) { bytes32 label = name.keccak(offset + 1, len); - (node, target) = getTarget( - name, - offset + len + 1 - ); + (node, target) = getTarget(name, offset + len + 1); node = keccak256(abi.encodePacked(node, label)); - if(targets[node] != address(0)){ - return ( - node, - targets[node] - ); + if (targets[node] != address(0)) { + return (node, targets[node]); } } else { - return ( - bytes32(0), - address(0) - ); + return (bytes32(0), address(0)); } return (node, target); } - /** + /** * @dev Resolve and verify a record stored in l2 target address. It supports subname by fetching target recursively to the nearlest parent. * @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) { + function resolve( + bytes calldata name, + bytes calldata data + ) external view returns (bytes memory result) { (, address target) = getTarget(name, 0); bytes4 selector = bytes4(data); if (selector == IAddrResolver.addr.selector) { - (bytes32 node) = abi.decode(data[4:], (bytes32)); + bytes32 node = abi.decode(data[4:], (bytes32)); return _addr(node, target); } if (selector == IAddressResolver.addr.selector) { - (bytes32 node, uint256 cointype) = abi.decode(data[4:], (bytes32, uint256)); + (bytes32 node, uint256 cointype) = abi.decode( + data[4:], + (bytes32, uint256) + ); return _addr(node, cointype, target); } if (selector == ITextResolver.text.selector) { - (bytes32 node, string memory key) = abi.decode(data[4:], (bytes32, string)); + (bytes32 node, string memory key) = abi.decode( + data[4:], + (bytes32, string) + ); return bytes(_text(node, key, target)); } if (selector == IContentHashResolver.contenthash.selector) { - (bytes32 node) = abi.decode(data[4:], (bytes32)); + bytes32 node = abi.decode(data[4:], (bytes32)); return _contenthash(node, target); } } - function _addr(bytes32 node, address target) private view returns (bytes memory) { - EVMFetcher.newFetchRequest(verifier, target) + function _addr( + bytes32 node, + address target + ) private view returns (bytes memory) { + EVMFetcher + .newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) - .element(node) + .element(node) .getDynamic(VERSIONABLE_ADDRESSES_SLOT) - .ref(0) - .element(node) - .element(COIN_TYPE_ETH) - .fetch(this.addrCallback.selector, ''); // recordVersions + .ref(0) + .element(node) + .element(COIN_TYPE_ETH) + .fetch(this.addrCallback.selector, msg.data[0:4]); // recordVersions } function addrCallback( bytes[] memory values, - bytes memory + bytes memory sig ) public pure returns (bytes memory) { - return abi.encode(address(bytes20(values[1]))); + address result = address(bytes20(values[1])); + if (keccak256(sig) != keccak256(hex"9061b923")) { + // Return address instead of bytes + assembly { + let freemem := mload(0x40) + mstore(freemem, result) + return(freemem, 0x20) + } + } + return abi.encode(result); } function _addr( @@ -155,20 +177,24 @@ contract L1Resolver is EVMFetchTarget { uint256 coinType, address target ) private view returns (bytes memory) { - EVMFetcher.newFetchRequest(verifier, target) + EVMFetcher + .newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) - .element(node) + .element(node) .getDynamic(VERSIONABLE_ADDRESSES_SLOT) - .ref(0) - .element(node) - .element(coinType) - .fetch(this.addrCoinTypeCallback.selector, ''); + .ref(0) + .element(node) + .element(coinType) + .fetch(this.addrCoinTypeCallback.selector, msg.data[0:4]); } function addrCoinTypeCallback( bytes[] memory values, - bytes memory + bytes memory sig ) public pure returns (bytes memory) { + if (keccak256(sig) != keccak256(hex"9061b923")) { + return values[1]; + } return abi.encode(values[1]); } @@ -177,38 +203,100 @@ contract L1Resolver is EVMFetchTarget { string memory key, address target ) private view returns (bytes memory) { - EVMFetcher.newFetchRequest(verifier, target) + EVMFetcher + .newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) - .element(node) + .element(node) .getDynamic(VERSIONABLE_TEXTS_SLOT) - .ref(0) - .element(node) - .element(key) - .fetch(this.textCallback.selector, ''); + .ref(0) + .element(node) + .element(key) + .fetch(this.textCallback.selector, msg.data[0:4]); } function textCallback( bytes[] memory values, - bytes memory + bytes memory sig ) public pure returns (bytes memory) { + if (keccak256(sig) != keccak256(hex"9061b923")) { + return bytes(string(values[1])); + } return abi.encode(string(values[1])); } - function _contenthash(bytes32 node, address target) private view returns (bytes memory) { - EVMFetcher.newFetchRequest(verifier, target) + function _contenthash( + bytes32 node, + address target + ) private view returns (bytes memory) { + EVMFetcher + .newFetchRequest(verifier, target) .getStatic(RECORD_VERSIONS_SLOT) - .element(node) + .element(node) .getDynamic(VERSIONABLE_HASHES_SLOT) - .ref(0) - .element(node) - .fetch(this.contenthashCallback.selector, ''); + .ref(0) + .element(node) + .fetch(this.contenthashCallback.selector, msg.data[0:4]); } function contenthashCallback( bytes[] memory values, - bytes memory + bytes memory sig ) public pure returns (bytes memory) { + if (keccak256(sig) != keccak256(hex"9061b923")) { + return values[1]; + } return abi.encode(values[1]); } + /** + * Returns the address associated with an ENS node. + * @param node The ENS node to query. + * @return The associated address. + */ + function addr( + bytes32 node + ) public view virtual override returns (address payable) { + _addr(node, targets[node]); + } + + function addr( + bytes32 node, + uint256 coinType + ) public view virtual override returns (bytes memory) { + _addr(node, coinType, targets[node]); + } + + /** + * 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( + bytes32 node, + string calldata key + ) external view virtual override returns (string memory) { + _text(node, key, targets[node]); + } + + /** + * Returns the contenthash associated with an ENS node. + * @param node The ENS node to query. + * @return The associated contenthash. + */ + function contenthash( + bytes32 node + ) external view virtual override returns (bytes memory) { + _contenthash(node, targets[node]); + } + + function supportsInterface( + bytes4 interfaceID + ) public view virtual override returns (bool) { + return + interfaceID == type(IAddrResolver).interfaceId || + interfaceID == type(IAddressResolver).interfaceId || + interfaceID == type(ITextResolver).interfaceId || + interfaceID == type(IContentHashResolver).interfaceId; + } } diff --git a/crosschain-resolver/deploy_l1/10_l1resolver.ts b/crosschain-resolver/deploy_l1/10_l1resolver.ts index 8de02b18..61b0e9e1 100644 --- a/crosschain-resolver/deploy_l1/10_l1resolver.ts +++ b/crosschain-resolver/deploy_l1/10_l1resolver.ts @@ -1,6 +1,9 @@ import {HardhatRuntimeEnvironment} from 'hardhat/types'; import {DeployFunction} from 'hardhat-deploy/types'; +const NAMEWRAPPER = { + 'sepolia': '0x0635513f179D50A207757E05759CbD106d7dFcE8', +} const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {deployments, getNamedAccounts} = hre; @@ -13,7 +16,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log({OP_VERIFIER_ADDRESS}) await deploy('L1Resolver', { from: deployer, - args: [OP_VERIFIER_ADDRESS], + args: [ + OP_VERIFIER_ADDRESS, + '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', + NAMEWRAPPER[hre.network.name], + ], log: true, }); }; diff --git a/crosschain-resolver/hardhat.config.ts b/crosschain-resolver/hardhat.config.ts index 9e54c70e..92a8c3d0 100644 --- a/crosschain-resolver/hardhat.config.ts +++ b/crosschain-resolver/hardhat.config.ts @@ -31,16 +31,31 @@ const config: HardhatUserConfig = { l2: "optimismGoerli", }, }, + sepolia: { + url: L1_PROVIDER_URL, + accounts: [DEPLOYER_PRIVATE_KEY], + deploy: [ "deploy_l1/" ], + companionNetworks: { + l2: "optimismSepolia", + }, + }, optimismGoerli: { url: "https://goerli.optimism.io", accounts: [DEPLOYER_PRIVATE_KEY], deploy: [ "deploy_l2/" ], + }, + optimismSepolia: { + url: "https://sepolia.optimism.io", + accounts: [DEPLOYER_PRIVATE_KEY], + deploy: [ "deploy_l2/" ], } }, etherscan: { apiKey: { goerli: L1_ETHERSCAN_API_KEY, - optimismGoerli: L2_ETHERSCAN_API_KEY + optimismGoerli: L2_ETHERSCAN_API_KEY, + sepolia: L1_ETHERSCAN_API_KEY, + optimismSepolia: L2_ETHERSCAN_API_KEY, }, customChains: [ { @@ -50,7 +65,15 @@ const config: HardhatUserConfig = { apiURL: "https://api-goerli-optimism.etherscan.io/api", browserURL: "https://goerli-optimism.etherscan.io" } - } + }, + { + network: "optimismSepolia", + chainId: 11155420, + urls: { + apiURL: "https://api-sepolia-optimism.etherscan.io/api", + browserURL: "https://sepolia-optimism.etherscan.io" + } + }, ] }, namedAccounts: { diff --git a/crosschain-resolver/package.json b/crosschain-resolver/package.json index f8b26c53..ff765a55 100644 --- a/crosschain-resolver/package.json +++ b/crosschain-resolver/package.json @@ -17,8 +17,8 @@ "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomicfoundation/hardhat-verify": "^1.0.0", "@nomiclabs/hardhat-ganache": "^2.0.1", - "@typechain/ethers-v6": "^0.4.0", - "@typechain/hardhat": "^8.0.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/express": "^4.17.18", "@types/mocha": ">=9.1.0", @@ -29,7 +29,7 @@ "express": "^4.18.2", "ganache": "^7.9.1", "hardhat": "^2.17.4", - "hardhat-deploy": "^0.11.43", + "hardhat-deploy": "^0.12.2", "hardhat-deploy-ethers": "^0.4.1", "hardhat-gas-reporter": "^1.0.8", "hardhat-storage-layout": "^0.1.7", @@ -37,12 +37,13 @@ "solidity-coverage": "^0.8.1", "supertest": "^6.3.3", "ts-node": "^10.9.1", - "typechain": "^8.2.0", + "typechain": "^8.3.1", "typescript": "^5.2.2" }, "dependencies": { - "@ensdomains/ens-contracts": "ensdomains/ens-contracts#delegatable-resolver-with-factory", - "@ensdomains/evm-verifier": "^0.1.0", - "@eth-optimism/contracts": "^0.6.0" + "@ensdomains/ens-contracts": "ensdomains/ens-contracts#delegatable-resolver-wo-factory", + "@ensdomains/evm-verifier": "workspace:*", + "@eth-optimism/contracts": "^0.6.0", + "clones-with-immutable-args": "wighawag/clones-with-immutable-args#master" } -} +} \ No newline at end of file diff --git a/l1-gateway/package.json b/l1-gateway/package.json index e63432b3..642e0309 100644 --- a/l1-gateway/package.json +++ b/l1-gateway/package.json @@ -58,7 +58,7 @@ "dependencies": { "@chainlink/ccip-read-server": "^0.2.1", "@commander-js/extra-typings": "^11.0.0", - "@ensdomains/evm-gateway": "^0.1.0", + "@ensdomains/evm-gateway": "workspace:*", "@ethereumjs/block": "^5.0.0", "@nomicfoundation/ethereumjs-block": "^5.0.2", "commander": "^11.0.0", diff --git a/l1-verifier/package.json b/l1-verifier/package.json index dc9cc669..0338c976 100644 --- a/l1-verifier/package.json +++ b/l1-verifier/package.json @@ -39,6 +39,6 @@ "dependencies": { "@eth-optimism/contracts": "^0.6.0", "@eth-optimism/contracts-bedrock": "^0.16.2", - "@ensdomains/evm-verifier": "^0.1.0" + "@ensdomains/evm-verifier": "workspace:*" } } diff --git a/op-gateway/package.json b/op-gateway/package.json index 91fcc538..9334d669 100644 --- a/op-gateway/package.json +++ b/op-gateway/package.json @@ -58,7 +58,7 @@ "dependencies": { "@chainlink/ccip-read-server": "^0.2.1", "@commander-js/extra-typings": "^11.0.0", - "@ensdomains/evm-gateway": "^0.1.0", + "@ensdomains/evm-gateway": "workspace:*", "@ethereumjs/block": "^5.0.0", "@nomicfoundation/ethereumjs-block": "^5.0.2", "commander": "^11.0.0", diff --git a/op-verifier/hardhat.config.ts b/op-verifier/hardhat.config.ts index 98f86054..aa566154 100644 --- a/op-verifier/hardhat.config.ts +++ b/op-verifier/hardhat.config.ts @@ -5,8 +5,8 @@ import { HardhatUserConfig } from 'hardhat/config'; import 'ethers' const DEPLOYER_PRIVATE_KEY = process.env.DEPLOYER_PRIVATE_KEY || "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; const L1_PROVIDER_URL = process.env.L1_PROVIDER_URL || ''; -const L1_ETHERSCAN_API_KEY = process.env.L1_ETHERSCAN_API_KEY; -const L2_ETHERSCAN_API_KEY = process.env.L2_ETHERSCAN_API_KEY; +const L1_ETHERSCAN_API_KEY = process.env.L1_ETHERSCAN_API_KEY || ''; +const L2_ETHERSCAN_API_KEY = process.env.L2_ETHERSCAN_API_KEY || ''; const config: HardhatUserConfig = { solidity: '0.8.19', @@ -32,16 +32,31 @@ const config: HardhatUserConfig = { l2: "optimismGoerli", }, }, + sepolia: { + url: L1_PROVIDER_URL, + accounts: [DEPLOYER_PRIVATE_KEY], + deploy: [ "deploy_l1/" ], + companionNetworks: { + l2: "optimismSepolia", + }, + }, optimismGoerli: { url: "https://goerli.optimism.io", accounts: [DEPLOYER_PRIVATE_KEY], deploy: [ "deploy_l2/" ], - } + }, + optimismSepolia: { + url: "https://sepolia.optimism.io", + accounts: [DEPLOYER_PRIVATE_KEY], + deploy: [ "deploy_l2/" ], + }, }, etherscan: { apiKey: { goerli: L1_ETHERSCAN_API_KEY, - optimismGoerli: L2_ETHERSCAN_API_KEY + optimismGoerli: L2_ETHERSCAN_API_KEY, + sepolia: L1_ETHERSCAN_API_KEY, + optimismSepolia: L2_ETHERSCAN_API_KEY, }, customChains: [ { @@ -51,7 +66,23 @@ const config: HardhatUserConfig = { apiURL: "https://api-goerli-optimism.etherscan.io/api", browserURL: "https://goerli-optimism.etherscan.io" } - } + }, + { + network: "sepolia", + chainId: 11155111, + urls: { + apiURL: "https://api-sepolia.etherscan.io/api", + browserURL: "https://sepolia.etherscan.io" + } + }, + { + network: "optimismSepolia", + chainId: 11155420, + urls: { + apiURL: "https://api-sepolia-optimism.etherscan.io/api", + browserURL: "https://sepolia-optimism.etherscan.io" + } + }, ] }, namedAccounts: { diff --git a/op-verifier/package.json b/op-verifier/package.json index 6d2795ae..29b811b9 100644 --- a/op-verifier/package.json +++ b/op-verifier/package.json @@ -13,10 +13,10 @@ "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@nomicfoundation/hardhat-verify": "^1.0.0", - "@typechain/ethers-v6": "^0.4.0", - "@typechain/hardhat": "^8.0.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.2.0", "@types/express": "^4.17.18", "@types/mocha": ">=9.1.0", @@ -26,18 +26,18 @@ "express": "^4.18.2", "ganache": "^7.9.1", "hardhat": "^2.16.0", - "hardhat-deploy": "^0.11.43", + "hardhat-deploy": "^0.12.2", "hardhat-deploy-ethers": "^0.4.1", "hardhat-gas-reporter": "^1.0.8", "solidity-bytes-utils": "^0.8.0", "solidity-coverage": "^0.8.1", "supertest": "^6.3.3", "ts-node": "^10.9.1", - "typechain": "^8.2.0", + "typechain": "^8.3.2", "typescript": "^5.2.2" }, "dependencies": { - "@ensdomains/evm-verifier": "^0.1.0", + "@ensdomains/evm-verifier": "workspace:*", "@eth-optimism/contracts": "^0.6.0", "@eth-optimism/contracts-bedrock": "^0.16.2" }