github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/contracts/ens/ens.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package ens 18 19 //go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go 20 //go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go 21 //go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go 22 23 import ( 24 "strings" 25 26 "github.com/intfoundation/intchain/accounts/abi/bind" 27 "github.com/intfoundation/intchain/common" 28 "github.com/intfoundation/intchain/contracts/ens/contract" 29 "github.com/intfoundation/intchain/core/types" 30 "github.com/intfoundation/intchain/crypto" 31 ) 32 33 var ( 34 MainNetAddress = common.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b") 35 TestNetAddress = common.HexToAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010") 36 ) 37 38 // swarm domain name registry and resolver 39 type ENS struct { 40 *contract.ENSSession 41 contractBackend bind.ContractBackend 42 } 43 44 // NewENS creates a struct exposing convenient high-level operations for interacting with 45 // the Ethereum Name Service. 46 func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) { 47 ens, err := contract.NewENS(contractAddr, contractBackend) 48 if err != nil { 49 return nil, err 50 } 51 52 return &ENS{ 53 &contract.ENSSession{ 54 Contract: ens, 55 TransactOpts: *transactOpts, 56 }, 57 contractBackend, 58 }, nil 59 } 60 61 // DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar. 62 func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) { 63 // Deploy the ENS registry. 64 ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend) 65 if err != nil { 66 return ensAddr, nil, err 67 } 68 69 ens, err := NewENS(transactOpts, ensAddr, contractBackend) 70 if err != nil { 71 return ensAddr, nil, err 72 } 73 74 // Deploy the registrar. 75 regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{}) 76 if err != nil { 77 return ensAddr, nil, err 78 } 79 // Set the registrar as owner of the ENS root. 80 if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil { 81 return ensAddr, nil, err 82 } 83 84 return ensAddr, ens, nil 85 } 86 87 func ensParentNode(name string) (common.Hash, common.Hash) { 88 parts := strings.SplitN(name, ".", 2) 89 label := crypto.Keccak256Hash([]byte(parts[0])) 90 if len(parts) == 1 { 91 return [32]byte{}, label 92 } else { 93 parentNode, parentLabel := ensParentNode(parts[1]) 94 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label 95 } 96 } 97 98 func ensNode(name string) common.Hash { 99 parentNode, parentLabel := ensParentNode(name) 100 return crypto.Keccak256Hash(parentNode[:], parentLabel[:]) 101 } 102 103 func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) { 104 resolverAddr, err := self.Resolver(node) 105 if err != nil { 106 return nil, err 107 } 108 109 resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend) 110 if err != nil { 111 return nil, err 112 } 113 114 return &contract.PublicResolverSession{ 115 Contract: resolver, 116 TransactOpts: self.TransactOpts, 117 }, nil 118 } 119 120 func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) { 121 registrarAddr, err := self.Owner(node) 122 if err != nil { 123 return nil, err 124 } 125 126 registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend) 127 if err != nil { 128 return nil, err 129 } 130 131 return &contract.FIFSRegistrarSession{ 132 Contract: registrar, 133 TransactOpts: self.TransactOpts, 134 }, nil 135 } 136 137 // Resolve is a non-transactional call that returns the content hash associated with a name. 138 func (self *ENS) Resolve(name string) (common.Hash, error) { 139 node := ensNode(name) 140 141 resolver, err := self.getResolver(node) 142 if err != nil { 143 return common.Hash{}, err 144 } 145 146 ret, err := resolver.Content(node) 147 if err != nil { 148 return common.Hash{}, err 149 } 150 151 return common.BytesToHash(ret[:]), nil 152 } 153 154 // Register registers a new domain name for the caller, making them the owner of the new name. 155 // Only works if the registrar for the parent domain implements the FIFS registrar protocol. 156 func (self *ENS) Register(name string) (*types.Transaction, error) { 157 parentNode, label := ensParentNode(name) 158 registrar, err := self.getRegistrar(parentNode) 159 if err != nil { 160 return nil, err 161 } 162 return registrar.Contract.Register(&self.TransactOpts, label, self.TransactOpts.From) 163 } 164 165 // SetContentHash sets the content hash associated with a name. Only works if the caller 166 // owns the name, and the associated resolver implements a `setContent` function. 167 func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) { 168 node := ensNode(name) 169 170 resolver, err := self.getResolver(node) 171 if err != nil { 172 return nil, err 173 } 174 175 opts := self.TransactOpts 176 opts.GasLimit = 200000 177 return resolver.Contract.SetContent(&opts, node, hash) 178 }