Quick(ish)start

Quick(ish)start

This quickstart outlines how to deploy a solution for resolving an ENS domain from one of our supported chains.

!! You can see that ethglobal.eth (opens in a new tab) resolves using this exact solution on Sepolia.

!! The resolver it is using is deployed and verified on Sepolia here (opens in a new tab).

!! The data contract is deployed and verified on Optimism Sepolia here (opens in a new tab).

1. Initial setup

Run these commands:

mkdir quickstart
cd quickstart
git init
forge install https://github.com/unruggable-labs/unruggable-gateways
mkdir contracts

2. Create a foundry.toml

  • Add the following configuration.
[profile.default]
src = "contracts"
libs = ["lib"]
solc = "0.8.25"
 
remappings = [
    "@unruggable=lib/unruggable-gateways/"
]

2. Deploy a data contract to L2

  • Create a file in your contracts directory called L2DataContract.sol
  • Copy the code below.
  • Replace YOUR-ADDRESS-HERE with your desired resolution address.

Contract code

L2DataContract.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
 
contract L2DataContract {
    address slot0 = YOUR-ADDRESS-HERE;
}
  • Replace YOUR-L2-RPC-URL with the RPC url for the L2 rollup you want to deploy to.
  • Replace YOUR-PRIVATE-KEY with your deployment private key.
  • Run the command.
forge create --rpc-url YOUR-L2-RPC-URL --private-key YOUR-PRIVATE-KEY contracts/L2DataContract.sol:L2DataContract

You should get an output similar to the below:

Deployed to: 0xbf6d2C96547Bb015961cb38D30596a781C7039e1
Transaction hash: 0x734bcee537c67bb4af120189ebdb90afebcdf1422568987a09546a55092808fc

3. Deploy a resolver to L1

  • Create a file in your contracts directory called L1SimpleResolver.sol
  • Copy the code below.
L1SimpleResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
 
import {GatewayFetcher, GatewayRequest} from "@unruggable/contracts/GatewayFetcher.sol";
import {GatewayFetchTarget} from "@unruggable/contracts/GatewayFetchTarget.sol";
import {IGatewayVerifier} from "@unruggable/contracts/IGatewayVerifier.sol";
  
contract L1SimpleResolver is GatewayFetchTarget {
	using GatewayFetcher for GatewayRequest;
 
	IGatewayVerifier immutable _verifier;
	address immutable _exampleAddress;
 
	constructor(IGatewayVerifier verifier, address exampleAddress) {
		_verifier = verifier;
        _exampleAddress = exampleAddress;
	}
 
    function supportsInterface(bytes4 x) external pure returns (bool) {
		return x == 0x01ffc9a7 /*https://eips.ethereum.org/EIPS/eip-165*/ || x == 0x3b3b57de; /*https://docs.ens.domains/ensip/1*/
	}
 
    function addr(bytes32 node) public view returns (address) {
 
        GatewayRequest memory r = GatewayFetcher
            .newRequest(1)
            .setTarget(_exampleAddress)
            .setSlot(0)
            .read()
            .setOutput(0);
 
		fetch(_verifier, r, this.addrCallback.selector);    
	}
	
    function addrCallback(bytes[] calldata values, uint8, bytes calldata extraData) external pure returns (address) {
        return abi.decode(values[0], (address));
	}
}
  • Replace YOUR-L1-RPC-URL with the RPC URL for your Layer 1 node.
  • Replace YOUR-PRIVATE-KEY with your deployment private key.
  • Replace VERIFIER-ADDRESS with the verifier address for your chosen L2. This can be found here.

!! Take note of finalization times.

!! Our Sepolia Verifiers/Gateways relax finalization rules for speed of development. Read more.

  • Replace THE-ADDRESS-OF-THE-CONTRACT-YOU-DEPLOYED-IN-THE-LAST-STEP with.. you guessed it ;)
  • Run the command.
forge create --rpc-url YOUR-L1-RPC-URL --private-key YOUR-PRIVATE-KEY contracts/L1SimpleResolver.sol:L1SimpleResolver --constructor-args VERIFIER-ADDRESS THE-ADDRESS-OF-THE-CONTRACT-YOU-DEPLOYED-IN-THE-LAST-STEP

You should get an output similar to the below:

[⠊] Compiling...
Deployed to: 0x44A40a4479E49e54B51269d2a143bB428205A806
Transaction hash: 0x61a7705f137a55bb2c7c3ddedc54ede64dfd6d856c8a1d31faf2fbb1339e7932

4. Set your resolver

Set the resolver for your ENS name to the address of the deployed L1 Resolver.

You can do this through the ENS App (opens in a new tab).

Note: Make sure you are connected to the correct network (Mainnet, Sepolia, or Holesky).

Update resolver using the ENS App

5. Verify

  • Verify that your name resolves as expected.

This easiest way to do this is to view your names profile on the ENS App:

https://app.ens.domains/YOUR-NAME-HERE.eth

!! You can see that ethglobal.eth (opens in a new tab) resolves using this exact solution on Sepolia.

!! The resolver it is using is deployed and verified on Sepolia here (opens in a new tab).

!! The data contract is deployed and verified on Optimism Sepolia here (opens in a new tab).

Help me !

For further guidance we recommend that you read through the rest of the documentation. Especially our examples section. If you still can't find an answer we would be happy to help you out on our Discord (opens in a new tab).

Here are some quicklinks to our example repos:

End-to-end Resolution Demo

These examples (opens in a new tab) demonstrates full end to end resolution using Unruggable Gateways.

Resolution Demo

Typescript VM Demo

These examples (opens in a new tab) demonstrates using our Typescript VM implementation to read values from an assortment of data types/structures.

Gateway Examples