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 calledL2DataContract.sol
- Copy the code below.
- Replace
YOUR-ADDRESS-HERE
with your desired resolution address.
Contract code
//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 calledL1SimpleResolver.sol
- Copy the code below.
// 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).
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.
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.