Skip to content

Commit

Permalink
Sepolia resolvers (#27)
Browse files Browse the repository at this point in the history
* Add crosschain resolver details

* Updated @ensdomains/ens-contracts ensdomains/ens-contracts#feature/crosschain-resolver-with-reverse-registrar to the latest commit

* Change slot

* Add ReverseRegistrar deployment details

* Update reverse registrar deployed addresses

* Add Op sepolia reverse registrar deployment info

* Added L1Resolver contract deployment details

* Remove comment out

* Add bun.lockb

* Update bun.lockb

* Change ens- ontracts to point to l2-deployment branch

* Fix failing test

* Update bun.lockb

* Add L2ReverseRegistrar to deps.sol on crosschain-resolver (was throwing error)

* Fix failing test

* Remove unused subheader

* Redeploy base l1 resolver

* Update README.md

* Added Base Reverse Resolver contract address

* Add Arbitrum Reverse Resolver deployement

* Redeploy ArbL1ReverseResolver with correct L2 Resolver Address

* Redeploy l2 contracts with official reverse record namespace (cointype.reverse)

* Sepolia resolvers with analytics (#30)

* WIP

* Fix errors

* Ignore favicon

* Update bun.lockb

* Fix lint error

* Update gateway url

* Add console.log

* Changed endpoint

* Update apiEndpoint

* Add sender and calldata to props

* Move Tracker to evm-gateway

* Revert "Move Tracker to evm-gateway"

This reverts commit 5d3ba37.

* WIP

* Downgrade to 4.20231121.0

* Bump it to the latest

* Add type

* Replace tracker with @ensdomains/server-analytics

* Pass custom apiEndpoint and props

* Add GATEWAY_DOMAIN and ENDPOINT_URL

* Point to correct branch

* Fix CORS problem

* Add gateway log tracker to OP

* Fix lint error

* Update readme

* 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
  • Loading branch information
makoto authored Apr 11, 2024
1 parent b868b70 commit 2af9e7b
Show file tree
Hide file tree
Showing 60 changed files with 5,330 additions and 352 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ _cjs
op-verifier/deployments/opDevnetL1
op-verifier/deployments/opDevnetL2
artifacts
deployments
cache
.env
typechain-types
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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
```
9 changes: 5 additions & 4 deletions arb-gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ cd arb-gateway
npm install -g wrangler
wrngler login
wrangler secret put L1_PROVIDER_URL
wrangler secret put L2_PROVIDER_URL
wrangler secret put L2_ROLLUP
yarn deploy
wrangler secret put L1_PROVIDER_URL --env sepolia
wrangler secret put L2_PROVIDER_URL --env sepolia
wrangler secret put L2_ROLLUP --env sepolia
wrangler secret put ENDPOINT_URL --env sepolia
yarn deploy --env sepolia
```

## How to test
Expand Down
3 changes: 2 additions & 1 deletion arb-gateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@
},
"dependencies": {
"@chainlink/ccip-read-server": "^0.2.1",
"@cloudflare/workers-types": "^4.20240117.0",
"@ensdomains/evm-gateway": "^0.1.0",
"@ensdomains/server-analytics": "0.0.1-alpha.2",
"@ethereumjs/block": "^5.0.0",
"@nomicfoundation/ethereumjs-block": "^5.0.2",
"commander": "^11.0.0",
"ethers": "^6.7.1"
},
"devDependencies": {
"@commander-js/extra-typings": "^11.0.0"

}
}
79 changes: 73 additions & 6 deletions arb-gateway/src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,49 @@
import { Request as CFWRequest } from '@cloudflare/workers-types';
import { Server } from '@ensdomains/ccip-read-cf-worker';
import type { Router } from '@ensdomains/evm-gateway';
import { InMemoryBlockCache } from './blockCache/InMemoryBlockCache.js';
import { Tracker } from '@ensdomains/server-analytics';
interface Env {
L1_PROVIDER_URL: string;
L2_PROVIDER_URL: string;
L2_ROLLUP: string;
GATEWAY_DOMAIN: string;
ENDPOINT_URL: string;
}
interface LogResult {
(request: CFWRequest, result: Response): Promise<Response>;
}

let app: Router, logResult: LogResult;

const decodeUrl = (url: string) => {
const trackingData = url.match(
/\/0x[a-fA-F0-9]{40}\/0x[a-fA-F0-9]{1,}\.json/
);
if (trackingData) {
return {
sender: trackingData[0].slice(1, 42),
calldata: trackingData[0].slice(44).replace('.json', ''),
};
} else {
return {};
}
};

async function fetch(request: CFWRequest, env: Env) {
// Set PROVIDER_URL under .dev.vars locally. Set the key as secret remotely with `wrangler secret put WORKER_PROVIDER_URL`
const {
L1_PROVIDER_URL,
L2_PROVIDER_URL,
L2_ROLLUP,
GATEWAY_DOMAIN,
ENDPOINT_URL,
} = env;
const tracker = new Tracker(GATEWAY_DOMAIN, {
apiEndpoint: ENDPOINT_URL,
enableLogging: true,
});

let app: Router;
async function fetch(request: Request, env: Env) {
// Loading libraries dynamically as a temp work around.
// Otherwise, deployment thorws "Error: Script startup exceeded CPU time limit." error
if (!app) {
Expand All @@ -17,13 +52,37 @@ async function fetch(request: Request, env: Env) {
const EVMGateway = (await import('@ensdomains/evm-gateway')).EVMGateway;
const ArbProofService = (await import('./ArbProofService.js'))
.ArbProofService;
// Set PROVIDER_URL under .dev.vars locally. Set the key as secret remotely with `wrangler secret put WORKER_PROVIDER_URL`
const { L1_PROVIDER_URL, L2_PROVIDER_URL, L2_ROLLUP } = env;

const l1Provider = new ethers.JsonRpcProvider(L1_PROVIDER_URL);
const l2Provider = new ethers.JsonRpcProvider(L2_PROVIDER_URL);

console.log({ L1_PROVIDER_URL, L2_PROVIDER_URL });
logResult = async (
request: CFWRequest,
result: Response
): Promise<Response> => {
if (request.url.match(/favicon/)) {
return result;
}
if (!result.body) {
return result;
}
const [streamForLog, streamForResult] = result.body.tee();
const logResultData = (
await new Response(streamForLog).json()
).data.substring(0, 200);
const props = decodeUrl(request.url);
await tracker.trackEvent(
request,
'result',
{ props: { ...props, result: logResultData } },
true
);
const myHeaders = new Headers();
myHeaders.set('Access-Control-Allow-Origin', '*');
myHeaders.set('Access-Control-Allow-Methods', 'GET,HEAD,POST,OPTIONS');
myHeaders.set('Access-Control-Max-Age', '86400');
return new Response(streamForResult, { ...result, headers: myHeaders });
};
const gateway = new EVMGateway(
new ArbProofService(
l1Provider,
Expand All @@ -37,7 +96,15 @@ async function fetch(request: Request, env: Env) {
gateway.add(server);
app = server.makeApp('/');
}
return app.handle(request);

const props = decodeUrl(request.url);
await tracker.trackEvent(
request,
'request',
{ props: { ...props, ...{} } },
true
);
return app.handle(request).then(logResult.bind(null, request));
}

export default {
Expand Down
4 changes: 3 additions & 1 deletion arb-gateway/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "arb-gateway-worker"
account_id = "15dcc9085cb794bb4f29d3e8177ac880"
main = "./src/worker.ts"
node_compat = true
compatibility_date = "2023-10-13"
compatibility_date = "2024-01-25"


[dev]
Expand All @@ -13,3 +13,5 @@ command = "yarn build"

[env.sepolia]
name = "arb-sepolia-gateway-worker"
[env.sepolia.vars]
GATEWAY_DOMAIN="arb-sepolia-gateway-worker.ens-cf.workers.dev"
2 changes: 2 additions & 0 deletions arb-verifier/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const config: HardhatUserConfig = {
url: L1_PROVIDER_URL,
accounts: [DEPLOYER_PRIVATE_KEY],
deploy: ['deploy_l1/'],
chainId:11155111,
companionNetworks: {
l2: 'arbitrumSepolia',
},
Expand All @@ -52,6 +53,7 @@ const config: HardhatUserConfig = {
deploy: ['deploy_l2/'],
},
arbitrumSepolia: {
chainId: 421614,
url: 'https://sepolia-rollup.arbitrum.io/rpc',
accounts: [DEPLOYER_PRIVATE_KEY],
deploy: [ "deploy_l2/" ],
Expand Down
8 changes: 5 additions & 3 deletions arb-verifier/test/testArbVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ describe('ArbVerifier', () => {
const rollupAddress = process.env.ROLLUP_ADDRESS;
// When testing against Goerli, replace with this address
// const rollupAddress = '0x45e5cAea8768F42B385A366D3551Ad1e0cbFAb17';

const chainId = hre.network.config.chainId
console.log(hre.network.config)
console.log({chainId})
const gateway = await makeArbGateway(
(hre.network.config as any).url,
(hre.network.config as any).url,
(hre.config.networks[hre.network.companionNetworks.l2] as any).url,
rollupAddress,
5,
chainId,
);
const server = new Server()
gateway.add(server)
Expand Down
Binary file modified bun.lockb
Binary file not shown.
1 change: 0 additions & 1 deletion crosschain-resolver/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ typechain-types
# Hardhat files
cache
artifacts
deployments

59 changes: 30 additions & 29 deletions crosschain-resolver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,28 @@ Storage verificaton can only verify the data of l2. When the function result nee
}
```

## Deploying (Sepolia)

Before deploying l1 contracts, deploy l2 contracts on https://github.com/ensdomains/ens-contracts

## Deploying (Goerli)
```
git clone https://github.com/ensdomains/ens-contracts
cd ens-contracts
DEPLOYER_KEY=$DEPLOYER_KEY ETHERSCAN_API_KEY=$ETHERSCAN_API_KEY npx hardhat deploy --tags l2 --network optimismSepolia/baseSepolia/arbSepolia
```

Create `.env` and set the following variables
Once l2 contracts are deployed, create `.env` and set the following variables

- DEPLOYER_PRIVATE_KEY
- L1_PROVIDER_URL
- L2_PROVIDER_URL
- L1_ETHERSCAN_API_KEY
- L2_ETHERSCAN_API_KEY
- VERIFIER_ADDRESS
- ENS_ADDRESS
- WRAPPER_ADDRESS
- L2_GRAPHQL_URL
```
bun run hardhat deploy --network optimismGoerli
```

Followed by the L1 contract:

```
bun run hardhat deploy --network goerli
bun run hardhat deploy --network sepolia
```

## Deployments
Expand All @@ -102,35 +102,37 @@ const l2Factory = new ethers.Contract(L2_RESOLVER_FACTORY_ADDRESS, abi, l2provid
const l2resolverAddress = await l2Factory.predictAddress(ETH_ADDRESS)
```

### OP
### OP on Sepolia

#### L2
- DelegatableResolver = [0xE00739Fc93e27aBf44343fD5FAA151c67C0A0Aa3](https://goerli-optimism.etherscan.io/address/0xE00739Fc93e27aBf44343fD5FAA151c67C0A0Aa3) = this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0xacB9771923873614d77C914D716d8E25dAF09b8d](https://goerli-optimism.etherscan.io/address/0xacB9771923873614d77C914D716d8E25dAF09b8d)
- DelegatableResolver = [0x017845E4518dB01EFCAFd7Acb192aF924B432d66](https://sepolia-optimism.etherscan.io/address/0x017845E4518dB01EFCAFd7Acb192aF924B432d66#code
) = this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0x79b784075600c5C420aC3CEd45f04EEA50306a96](https://sepolia-optimism.etherscan.io/address/0x79b784075600c5C420aC3CEd45f04EEA50306a96#code)

#### L1
- OPVerifier = [0xe58448bfc2fa097953e800e0af0b0a5257ecc4b1](https://goerli.etherscan.io/address/0xe58448bfc2fa097953e800e0af0b0a5257ecc4b1)
- L1Resolver = [0x7Bf57B0a683CC964B0fEe30633A72F5c05464a0f](https://goerli.etherscan.io/address/0x7Bf57B0a683CC964B0fEe30633A72F5c05464a0f) = Currently `op.evmgateway.eth` is set to the resolver
- OPVerifier = [0x0e8DA38565915B7e74e2d78F80ba1BF815F34116](https://sepolia.etherscan.io/address/0x0e8DA38565915B7e74e2d78F80ba1BF815F34116#code)
- L1Resolver = [0x57C1f50093C1017AE81EBAF336511ACcc48061e2](https://sepolia.etherscan.io/address/0x57C1f50093C1017AE81EBAF336511ACcc48061e2#code) = Currently `op.evmgateway.eth` is set to the resolver

### Base
### Base on Sepolia

#### L2
- DelegatableResolver = [0x60BDFeF9ff7bB47d95d1658Be925587F046AE2C7](https://goerli.basescan.org/address/0x7d56Bc48F0802319CB7C79B421Fa5661De905AF7) = this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0x7d56Bc48F0802319CB7C79B421Fa5661De905AF7](https://goerli.basescan.org/address/0x7d56Bc48F0802319CB7C79B421Fa5661De905AF7)
- DelegatableResolver = [0xd8A6B88b0a0B419fCce6cfBD60F21f1b7761eeB2](https://sepolia.basescan.org/address/0xd8A6B88b0a0B419fCce6cfBD60F21f1b7761eeB2#code) = this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0xCcFC8Be7f65E1D46Af71cf6C06668DDA25f51e3e](https://sepolia.basescan.org/address/0xCcFC8Be7f65E1D46Af71cf6C06668DDA25f51e3e#code)

#### L1
- OPVerifier = [0x7e2f9c4a1467e8a41e1e8283ba3ba72e3d92f6b8](https://goerli.etherscan.io/address/0x7e2f9c4a1467e8a41e1e8283ba3ba72e3d92f6b8)
- L1Resolver = [0x3Ac25843A1F696fe2166C5dE127FD4f2832F4d42](https://goerli.etherscan.io/address/0x3Ac25843A1F696fe2166C5dE127FD4f2832F4d42) = Currently `base.evmgateway.eth` is set to the resolver
- OPVerifier = [0xAdef74372444e716C0473dEe1F9Cb3108EFa3818](https://sepolia.etherscan.io/address/0xAdef74372444e716C0473dEe1F9Cb3108EFa3818#code
)
- L1Resolver = [0xF6EfB10e47d6D4C1023BBFa5e6396B00915FbD41](https://sepolia.etherscan.io/address/0xF6EfB10e47d6D4C1023BBFa5e6396B00915FbD41#code) = Currently `base.evmgateway.eth` is set to the resolver

### Arbitrum
### Arbitrum on Sepolia

#### L2
- DelegatableResolver = [0x5F5e99139a17c56eadC3B1d01535224d003B7E5b](https://goerli.arbiscan.io/address/0x5F5e99139a17c56eadC3B1d01535224d003B7E5b) this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0x94fbCE7ca1a0152cfC99F90f4421d31cf356c896](https://goerli.arbiscan.io/address/0x94fbCE7ca1a0152cfC99F90f4421d31cf356c896)
- [0xf91e7d97e4dbb5303f047b135247073d7991cbdb]
- DelegatableResolver = [0xCcFC8Be7f65E1D46Af71cf6C06668DDA25f51e3e](https://api-sepolia.arbiscan.io/address/0xCcFC8Be7f65E1D46Af71cf6C06668DDA25f51e3e#code) this is used as a template so cannot interact directly
- DelegatableResolverFactory = [0xF2c102E96A183fC598d83fDccF4e30cfE83aedCd](https://api-sepolia.arbiscan.io/address/0xF2c102E96A183fC598d83fDccF4e30cfE83aedCd#code)

#### L1
- ArbVerifier = [0x9E46DeE08Ad370bEFa7858c0E9a6c87f2D7E57A1](https://goerli.etherscan.io/address/0x9E46DeE08Ad370bEFa7858c0E9a6c87f2D7E57A1#code)
- L1Resolver = [0xFb42a2d1A28A10607ee426764BdcdA7d121731AD](https://goerli.etherscan.io/address/0xFb42a2d1A28A10607ee426764BdcdA7d121731AD#code)
- ArbVerifier = [0x6820E47CED34D6F275c6d26C3876D48B2c1fdf27](https://sepolia.etherscan.io/address/0x6820E47CED34D6F275c6d26C3876D48B2c1fdf27#code)
- L1Resolver = [0xA47b9B72571e23604f067dfd4F22785c33E9cF9c](https://sepolia.etherscan.io/address/0xA47b9B72571e23604f067dfd4F22785c33E9cF9c#code) = Currently `arb.evmgateway.eth` is set to the resolver

## Usage

Expand Down Expand Up @@ -167,7 +169,7 @@ DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY L1_PROVIDER_URL=$L1_PROVIDER_URL L2_P
```

```
DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY L1_PROVIDER_URL=$L1_PROVIDER_URL L2_PROVIDER_URL=$L2_PROVIDER_URL L1_ETHERSCAN_API_KEY=$L1_ETHERSCAN_API_KEY L2_ETHERSCAN_API_KEY=$L2_ETHERSCAN_API_KEY L2_PROVIDER_URL=$L2_PROVIDER_URL L2_RESOLVER_FACTORY_ADDRESS=$L2_RESOLVER_FACTORY_ADDRESS ENS_NAME=$ENS_NAME yarn setupl2
DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY L1_PROVIDER_URL=$L1_PROVIDER_URL L2_PROVIDER_URL=$L2_PROVIDER_URL L1_ETHERSCAN_API_KEY=$L1_ETHERSCAN_API_KEY L2_ETHERSCAN_API_KEY=$L2_ETHERSCAN_API_KEY L2_PROVIDER_URL=$L2_PROVIDER_URL L2_RESOLVER_FACTORY_ADDRESS=$L2_RESOLVER_FACTORY_ADDRESS ENS_NAME=$ENS_NAME yarn setupl2 --network optimismSepolia/baseSepolia/arbitrumSepolia
```

```
Expand All @@ -192,8 +194,7 @@ await DelegatableResolver.approve(encodedname, OWNER_ADDRESS, true)
Using the script

```
OPERATOR_ADDRESS=0x5A384227B65FA093DEC03Ec34e111Db80A040615
DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY L1_PROVIDER_URL=$L1_PROVIDER_URL L2_PROVIDER_URL=$L2_PROVIDER_URL L1_ETHERSCAN_API_KEY=$L1_ETHERSCAN_API_KEY L2_ETHERSCAN_API_KEY=$L2_ETHERSCAN_API_KEY L2_PROVIDER_URL=$L2_PROVIDER_URL L2_RESOLVER_FACTORY_ADDRESS=$L2_RESOLVER_FACTORY_ADDRESS ENS_SUBNAME=$ENS_SUBNAME yarn approve
OPERATOR_ADDRESS=$OPERATOR_ADDRESS DEPLOYER_PRIVATE_KEY=$DEPLOYER_PRIVATE_KEY L1_PROVIDER_URL=$L1_PROVIDER_URL L2_PROVIDER_URL=$L2_PROVIDER_URL L1_ETHERSCAN_API_KEY=$L1_ETHERSCAN_API_KEY L2_ETHERSCAN_API_KEY=$L2_ETHERSCAN_API_KEY L2_PROVIDER_URL=$L2_PROVIDER_URL L2_RESOLVER_FACTORY_ADDRESS=$L2_RESOLVER_FACTORY_ADDRESS ENS_SUBNAME=$ENS_SUBNAME yarn approve --network optimismSepolia/baseSepolia/arbSepolia
```

Once done, set addrss of the subname from the operator, wait 10~20 min, then query the subname on L1
Expand Down
7 changes: 7 additions & 0 deletions crosschain-resolver/contracts/IAddrSetter.sol
Original file line number Diff line number Diff line change
@@ -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);
}

16 changes: 2 additions & 14 deletions crosschain-resolver/contracts/IMetadataResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
}
Loading

0 comments on commit 2af9e7b

Please sign in to comment.