Cross Chain / Offchain Resolvers
The source of truth for a name and its subdomains does not always have to be on-chain or on Ethereum L1 at all. By leveraging EIP-3668, the Cross Chain Interoperability Protocol (or CCIP Read for short), we can load information by hitting a so called "Gateway". Within the context of ENS, this enables us, to read names, addresses, records, and more from other chains, or even off-chain.
The Cross Chain Interoperability Protocol (CCIP Read), is a client-side implemented protocol that introduces the OffchainLookup error. Once the client encounters this error, it will attempt to handle it by calling a gateway url. Most Ethereum libraries handle this for you, at no additional cost.
error OffchainLookup(
address sender,
string[] urls,
bytes callData,
bytes4 callbackFunction,
bytes extraData
)
An example of CCIP Read in action can be found at offchain.ens.gregskril.com. This example application allows you to claim a subname for 24 hours. The name offchaindemo.eth with resolver 0xDB3...4D27, reverts with OffchainLookup and directs the client to a gateway url. The gateway url returns the information and loads it from a temporary database.
The EVMGateway is a gateway that allows you to load data from specific Layer 2's whose proofs are verifyable on L1. This means if you are looking to load data from Optimism or Arbitrum, the EVMGateway allows you to trustlessly do so.
When a name is looked up the resolver responsible is called to resolve the name.
During this execution the OffchainLookup
error is thrown, and the client will attempt to reach out to the gateway specified by the error.
If successful the gateways results are returned to the callback function specified in the error.
The output of the callback function is then returned to the client and considered the result of the original lookup.
A gateway is an off-chain service that is responsible for returning the data requested by a client.
A gateway must be implemented using the Gateway Interface as specified in EIP-3668.
This means it must expose an API served over https, and return data in a specific format.
This service can be a server, a serverless function, worker, etc.
The URL for this gateway is determined by the OffchainLookup
error, and is passed as a parameter to the error.
CCIP Read Offchain ENS Resolver with Cloudflare Workers
●TypeScript14061ensdomains/offchain-gateway-rsOffchain CCIP Read Gateway Resolver implementation in Rust (& postgres)
●Rustensdomains/offchain-resolver-exampleCCIP Offchain ENS Resolver example implementation
●TypeScript21gskril/ens-offchain-resolver-read-from-apiCCIP Read gateway that relays data from an external API
●TypeScriptThere are two methods (GET and POST) you can choose to implement when writing a gateway. When your smart-contract reverts with the OffchainLookup
error you can decide the url it returns.
If {data}
can be successfully substituted out of the URL a GET request will be made, if no {data}
is present a POST request will be made instead, with the data instead submitted as the post body.
// POST if URL does not include '{data}' parameter
URL: https://example.com/gateway/{sender}.json
Method: POST
Body: data
// GET if URL includes '{data}' parameter
URL: https://example.com/gateway/{sender}/{data}.json
Method: GET
- Name
sender
- Type
- address
- Description
Lowercased address of the contract reverting with the
OffchainLookup
error.
- Name
data
- Type
- bytes
- Description
0x prefixed bytes of the data passed to the
OffchainLookup
error.
The gateways response is returned to a callback function on the resolver, we assume this function verifies the data returned by the gateway. Gateways form a "one-of-many" trust relationship as we require only one gateway to be honest for the system to keep functioning.
Once you have written your gateway you need to deploy a resolver contract. For ready-to-deploy contracts check the demo's above or visit ccip.tools. If you would like to read more about writing your own resolver checkout the Writing a Resolver guide.
The gist is that this resolver must implement the specifications you plan to support (such as addr()
or resolve()
), and then revert with OffchainLookup
and your gateway URL.
When reverting with an OffchainLookup
error you can specify a callback function.
The callback function is evaluated on the client side with the data returned from the gateway.
This makes it a perfect place to validate proofs, signatures, or other data.
Last but not least you need to instruct your name to use the resolver-gateway combo. To do this, simply visit the ENS Manager App and set the resolver of your name to the contract address of your resolver. This means that all resolution for this name from now on will be handled by your resolver.
An alternative option is to set the Resolver manually or from a dApp.
To test your gateway you can use the ENS Manager App or if you want more detail try using enstate and notice the ccip_urls
field.
If your results are loaded successfully, you have successfully implemented a gateway resolver.
A testing tool for CCIP Read functions will be available soon.