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  }