Skip to content

Instantly share code, notes, and snippets.

@sterlu
Last active January 12, 2022 10:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sterlu/9e47011baedf60921b12d7c3183e25ba to your computer and use it in GitHub Desktop.
Save sterlu/9e47011baedf60921b12d7c3183e25ba to your computer and use it in GitHub Desktop.
Registering an ENS domain and setting up reverse lookup
// Disclamer:
// We are assuming Web3@1.0 is instantiated with a MetaMask provider or similar
const yourAccount = (await web3.eth.getAccounts())[0].toLowerCase()
function namehash(name) {
var node = '0x0000000000000000000000000000000000000000000000000000000000000000';
if (name !== '') {
var labels = name.split(".");
for(var i = labels.length - 1; i >= 0; i--) {
node = web3.utils.sha3(node + web3.utils.sha3(labels[i]).slice(2), {encoding: 'hex'});
}
}
return node.toString();
}
const ensAbi = [{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}]
// https://github.com/ensdomains/ens/blob/master/contracts/ENSRegistry.sol
const ens = new web3.eth.Contract(ensAbi, '0x112234455c3a32fd11230c42e7bccd4a84e02010');
const registrarAbi = [{"constant":true,"inputs":[],"name":"ens","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"expiryTimes","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"subnode","type":"bytes32"},{"name":"owner","type":"address"}],"name":"register","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"rootNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"},{"name":"node","type":"bytes32"}],"type":"constructor"}]
// https://github.com/ensdomains/ens/blob/master/contracts/TestRegistrar.sol
const registrarAddress = await ens.methods.owner(namehash('test')).call() // 0x21397c1A1F4aCD9132fE36Df011610564b87E24b
// We can get the registry for eth domains in the same way.
const registrar = new web3.eth.Contract(registrarAbi, registrarAddress);
// Buy domain (free on ropsten - valid for 28 days)
await registrar.methods.register(web3.utils.sha3("sterlu"), yourAccount).send({from: yourAccount})
// Set resolver for our domain. Resolver can have different records & metadata for domain.
await ens.methods.setResolver(namehash('sterlu.test'), '0x4c641fb9bad9b60ef180c31f56051ce826d21a9a').send({from: yourAccount})
await ens.methods.resolver(namehash('sterlu.test')).call()
// 0x4c641fb9bad9b60ef180c31f56051ce826d21a9a
const publicResolverAbi = [{"constant":true,"inputs":[{"name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"name","outputs":[{"name":"ret","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"hash","type":"bytes32"}],"name":"setContent","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"addr","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"x","type":"bytes32"},{"indexed":false,"name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"}]
// https://github.com/ensdomains/ens/blob/master/contracts/PublicResolver.sol
const publicResolver = new web3.eth.Contract(publicResolverAbi, '0x4c641fb9bad9b60ef180c31f56051ce826d21a9a');
// get address of reverseRegistrar
const reverseRegistarAddr = await ens.methods.owner(namehash('addr.reverse')).call()
// 0x67d5418a000534a8F1f5FF4229cC2f439e63BBe2
const reverseRegistrarAbi = [{"constant":false,"inputs":[{"name":"owner","type":"address"},{"name":"resolver","type":"address"}],"name":"claimWithResolver","outputs":[{"name":"node","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner","type":"address"}],"name":"claim","outputs":[{"name":"node","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"ens","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"defaultResolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"node","outputs":[{"name":"ret","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name","type":"string"}],"name":"setName","outputs":[{"name":"node","type":"bytes32"}],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"},{"name":"resolverAddr","type":"address"}],"payable":false,"type":"constructor"}]
// https://github.com/ensdomains/ens/blob/master/contracts/ReverseRegistrar.sol
const reverseRegistrar = new web3.eth.Contract(reverseRegistrarAbi, reverseRegistarAddr)
// await reverseRegistrar.methods.claim(yourAccount).send({ from: yourAccount })
await ens.methods.owner(namehash(yourAccount.substr(2) + '.addr.reverse')).call()
// 0x67d5418a000534a8F1f5FF4229cC2f439e63BBe2
// set resolver & call setName on resolver
await reverseRegistrar.methods.setName('sterlu.test').send({ from: yourAccount })
const reverseResolverAddr = await ens.methods.resolver(namehash(yourAccount.substr(2) + '.addr.reverse')).call()
// 0x53350F4089B10E516c164497f395Dbbbc8675e20 - defaultResolver from reverserResolver
const reverseResolver = new web3.eth.Contract(publicResolverAbi, reverseResolverAddr);
await reverseResolver.methods.name(namehash(yourAccount.substr(2) + '.addr.reverse')).call()
// sterlu.test
// ABIs from https://github.com/ensdomains/ens-manager/blob/master/src/api/ens.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment