ens的注册,与反向解析 (以文章时间的ens网站注册和解析地址为例)
ETHRegistrarController: 0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5
BaseRegistrarImplementation(域名nft) :0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85
ENSRegistryWithFallback(ens):0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
ReverseRegistrar:0x084b1c3C81545d370f3634392De611CaaBFf8148
DefaultReverseResolver:0xA2C122BE93b0074270ebeE7f6b7292C7deB45047
PublicResolver:0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41
注册
用户 -> ETHRegistrarController -> makeCommitmentWithConfig(string memory name, address owner, bytes32 secret, address resolver, address addr)查询不需要gas
用户 -> commit(bytes32 commitment) public commit上一步的返回值
用户 -> registerWithConfig 注册
function registerWithConfig(string memory name, address owner, uint duration, bytes32 secret, address resolver, address addr) public payable {
bytes32 commitment = makeCommitmentWithConfig(name, owner, secret, resolver, addr);
uint cost = _consumeCommitment(name, duration, commitment); //验证一下时间和域名是否被注册 获取需要支付的eth
bytes32 label = keccak256(bytes(name));
uint256 tokenId = uint256(label); //tokenId 是名字的hash
uint expires;
if(resolver != address(0)) {
// Set this contract as the (temporary) owner, giving it
// permission to set up the resolver.
expires = base.register(tokenId, address(this), duration); // 1
// The nodehash of this label
bytes32 nodehash = keccak256(abi.encodePacked(base.baseNode(), label));
// Set the resolver
base.ens().setResolver(nodehash, resolver); // 2
// Configure the resolver
if (addr != address(0)) {
Resolver(resolver).setAddr(nodehash, addr); // 3
}
// Now transfer full ownership to the expeceted owner
base.reclaim(tokenId, owner); //4
base.transferFrom(address(this), owner, tokenId); //把域名nft转移给用户
} else {
require(addr == address(0));
expires = base.register(tokenId, owner, duration);
}
emit NameRegistered(name, label, owner, cost, expires);
// Refund any extra payment
if(msg.value > cost) {
msg.sender.transfer(msg.value - cost); //退钱
}
}
1 BaseRegistrarImplementation -> register
function register(uint256 id, address owner, uint duration) external returns(uint) {
return _register(id, owner, duration, true);
}
function available(uint256 id) public view returns(bool) {
// Not available if it's registered here or in its grace period.
return expiries[id] + GRACE_PERIOD < now;
}
function _register(uint256 id, address owner, uint duration, bool updateRegistry) internal live onlyController returns(uint) { //owner 是 controller 合约
require(available(id)); //
require(now + duration + GRACE_PERIOD > now + GRACE_PERIOD); // Prevent future overflow
expiries[id] = now + duration;
if(_exists(id)) {
// Name was previously owned, and expired
_burn(id);
}
_mint(owner, id); //mint 域名nft
if(updateRegistry) {// baseNode The namehash of the TLD this registrar owns (eg, .eth) 也就是以.eth结尾
ens.setSubnodeOwner(baseNode, bytes32(id), owner); 1.1
}
emit NameRegistered(id, owner, now + duration);
return now + duration;
}
1.1 ens -> setSubnodeOwner 有权限限制 require(owner == msg.sender || operators[owner][msg.sender]); 调用者被授权或者是basenode的所有者
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) public authorised(node) returns(bytes32) {
bytes32 subnode = keccak256(abi.encodePacked(node, label));
_setOwner(subnode, owner);
emit NewOwner(node, label, owner);
return subnode;
}
2 ens -> setResolver 设置正向解析器 有权限限制 require(owner == msg.sender || operators[owner][msg.sender]); 调用者被授权或者是basenode的所有者
function setResolver(bytes32 node, address resolver) public authorised(node) { //resolver 是由用户注册时填的 可以自己定制
emit NewResolver(node, resolver);
records[node].resolver = resolver;
}
3 PublicResolver -> setAddr 设置域名解析出来对应的地址 由方法addr(bytes32 node)获取
function setAddr(bytes32 node, uint coinType, bytes memory a) public authorised(node) {
emit AddressChanged(node, coinType, a);
if(coinType == COIN_TYPE_ETH) {
emit AddrChanged(node, bytesToAddress(a));
}
_addresses[node][coinType] = a;
}
4 BaseRegistrarImplementation -> reclaim //把node的owner权限移交给用户
function reclaim(uint256 id, address owner) external live { //owner 为用户填入的注册域名所有者
require(_isApprovedOrOwner(msg.sender, id));
ens.setSubnodeOwner(baseNode, bytes32(id), owner); //参照 1.1
}
node的生成 bytes32 subnode = keccak256(abi.encodePacked(node, label));
域名的注册和正向解析完成
反向解析,反向解析类似给地址设置昵称,当前合约并不限制昵称必须是域名,但是ens设置反向解析时前端有限制。也就是可以跳过前端给你的地址设置任意昵称,我在rinkeby设置后在gnosissafe可以正常显示 比如我给我地址设置反向解析为aaa.btc
ReverseRegistrar -> setName
function claimWithResolver(address owner, address resolver) public returns (bytes32) { //owner 为 ReverseRegistrar 这里说明这个子节点的owner权限为ReverseRegistrar
bytes32 label = sha3HexAddress(msg.sender);
bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));
address currentOwner = ens.owner(node);
// Update the resolver if required
if (resolver != address(0x0) && resolver != ens.resolver(node)) {
// Transfer the name to us first if it's not already
if (currentOwner != address(this)) {
//ADDR_REVERSE_NODE = namehash('addr.reverse')
ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, address(this)); //参照1.1
currentOwner = address(this);
}
ens.setResolver(node, resolver);
}
// Update the owner if required
if (currentOwner != owner) {
ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);
}
return node;
}
function setName(string memory name) public returns (bytes32) {
bytes32 node = claimWithResolver(address(this), address(defaultResolver));
defaultResolver.setName(node, name); //5
return node;
}
5 DefaultReverseResolver -> setName
function setName(bytes32 node, string memory _name) public onlyOwner(node) {
name[node] = _name;
}
根据地址获取昵称 mapping (bytes32 => string) public name; =》 name(node) node 可以根据地址算出来
bytes32 label = sha3HexAddress(msg.sender); //msg.sender -> 地址
bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label));
以上!