ETH Price: $2,905.99 (-3.41%)
Gas: 11 Gwei

Transaction Decoder

Block:
8918653 at Nov-12-2019 05:36:57 AM +UTC
Transaction Fee:
0.000124603 ETH $0.36
Gas Used:
124,603 Gas / 1 Gwei

Emitted Events:

178 BaseRegistrarImplementation.Transfer( from=0x00000000...000000000, to=[Sender] 0xd5d171a9aa125af13216c3213b5a9fc793fccf2c, tokenId=45517853210629844263899512311815895959056074291434384731856636294373543610090 )
179 ENS.NewOwner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE, label=64A23122F315FA2585B0FE55A5F0E1976897B9139779FA444F768DF484E586EA, owner=[Sender] 0xd5d171a9aa125af13216c3213b5a9fc793fccf2c )
180 BaseRegistrarImplementation.NameRegistered( id=45517853210629844263899512311815895959056074291434384731856636294373543610090, owner=[Sender] 0xd5d171a9aa125af13216c3213b5a9fc793fccf2c, expires=1605093969 )
181 ETHRegistrarController.NameRegistered( name=ceshi, label=64A23122F315FA2585B0FE55A5F0E1976897B9139779FA444F768DF484E586EA, owner=[Sender] 0xd5d171a9aa125af13216c3213b5a9fc793fccf2c, cost=26901749699243524, expires=1605093969 )

Account State Difference:

  Address   Before After State Difference Code
0x31415926...173C1259b
(ENS: Eth Name Service)
(Spark Pool)
12.637874236625398973 Eth12.637998839625398973 Eth0.000124603
0xB22c1C15...020E6Ad16
(ENS: Old ETH Registrar Controller 2)
603.828232259109977906 Eth603.85513400880922143 Eth0.026901749699243524
0xd5D171a9...793FcCF2c
0.601675395781812288 Eth
Nonce: 38
0.574649043082568764 Eth
Nonce: 39
0.027026352699243524
0xFaC7BEA2...556b31e04

Execution Trace

ETH 0.026901749699243524 ETHRegistrarController.register( name=ceshi, owner=0xd5D171a9AA125AF13216C3213B5A9Fc793FcCF2c, duration=31556952, secret=7893070B719627504D0A89E2E8EB5E26C352D3ADE63EE6B65798784F6F110360 )
  • BaseRegistrarImplementation.available( id=45517853210629844263899512311815895959056074291434384731856636294373543610090 ) => ( True )
    • Registrar.state( _hash=64A23122F315FA2585B0FE55A5F0E1976897B9139779FA444F768DF484E586EA ) => ( 0 )
    • BaseRegistrarImplementation.nameExpires( id=45517853210629844263899512311815895959056074291434384731856636294373543610090 ) => ( 0 )
    • StablePriceOracle.price( name=ceshi, 0, duration=31556952 ) => ( 26901749699243524 )
      • Medianizer.STATICCALL( )
      • BaseRegistrarImplementation.register( id=45517853210629844263899512311815895959056074291434384731856636294373543610090, owner=0xd5D171a9AA125AF13216C3213B5A9Fc793FcCF2c, duration=31556952 ) => ( 1605093969 )
        • ENS.owner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE ) => ( 0xFaC7BEA255a6990f749363002136aF6556b31e04 )
        • Registrar.state( _hash=64A23122F315FA2585B0FE55A5F0E1976897B9139779FA444F768DF484E586EA ) => ( 0 )
        • ENS.setSubnodeOwner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE, label=64A23122F315FA2585B0FE55A5F0E1976897B9139779FA444F768DF484E586EA, owner=0xd5D171a9AA125AF13216C3213B5A9Fc793FcCF2c )
          File 1 of 6: ETHRegistrarController
          // File: contracts/PriceOracle.sol
          
          pragma solidity >=0.4.24;
          
          interface PriceOracle {
              /**
               * @dev Returns the price to register or renew a name.
               * @param name The name being registered or renewed.
               * @param expires When the name presently expires (0 if this is a new registration).
               * @param duration How long the name is being registered or extended for, in seconds.
               * @return The price of this renewal or registration, in wei.
               */
              function price(string calldata name, uint expires, uint duration) external view returns(uint);
          }
          
          // File: @ensdomains/ens/contracts/ENS.sol
          
          pragma solidity >=0.4.24;
          
          interface ENS {
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          
          
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external;
              function setResolver(bytes32 node, address resolver) external;
              function setOwner(bytes32 node, address owner) external;
              function setTTL(bytes32 node, uint64 ttl) external;
              function owner(bytes32 node) external view returns (address);
              function resolver(bytes32 node) external view returns (address);
              function ttl(bytes32 node) external view returns (uint64);
          
          }
          
          // File: @ensdomains/ens/contracts/Deed.sol
          
          pragma solidity >=0.4.24;
          
          interface Deed {
          
              function setOwner(address payable newOwner) external;
              function setRegistrar(address newRegistrar) external;
              function setBalance(uint newValue, bool throwOnFailure) external;
              function closeDeed(uint refundRatio) external;
              function destroyDeed() external;
          
              function owner() external view returns (address);
              function previousOwner() external view returns (address);
              function value() external view returns (uint);
              function creationDate() external view returns (uint);
          
          }
          
          // File: @ensdomains/ens/contracts/Registrar.sol
          
          pragma solidity >=0.4.24;
          
          
          interface Registrar {
          
              enum Mode { Open, Auction, Owned, Forbidden, Reveal, NotYetAvailable }
          
              event AuctionStarted(bytes32 indexed hash, uint registrationDate);
              event NewBid(bytes32 indexed hash, address indexed bidder, uint deposit);
              event BidRevealed(bytes32 indexed hash, address indexed owner, uint value, uint8 status);
              event HashRegistered(bytes32 indexed hash, address indexed owner, uint value, uint registrationDate);
              event HashReleased(bytes32 indexed hash, uint value);
              event HashInvalidated(bytes32 indexed hash, string indexed name, uint value, uint registrationDate);
          
              function state(bytes32 _hash) external view returns (Mode);
              function startAuction(bytes32 _hash) external;
              function startAuctions(bytes32[] calldata _hashes) external;
              function newBid(bytes32 sealedBid) external payable;
              function startAuctionsAndBid(bytes32[] calldata hashes, bytes32 sealedBid) external payable;
              function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) external;
              function cancelBid(address bidder, bytes32 seal) external;
              function finalizeAuction(bytes32 _hash) external;
              function transfer(bytes32 _hash, address payable newOwner) external;
              function releaseDeed(bytes32 _hash) external;
              function invalidateName(string calldata unhashedName) external;
              function eraseNode(bytes32[] calldata labels) external;
              function transferRegistrars(bytes32 _hash) external;
              function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) external;
              function entries(bytes32 _hash) external view returns (Mode, address, uint, uint, uint);
          }
          
          // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title IERC165
           * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
           */
          interface IERC165 {
              /**
               * @notice Query if a contract implements an interface
               * @param interfaceId The interface identifier, as specified in ERC-165
               * @dev Interface identification is specified in ERC-165. This function
               * uses less than 30,000 gas.
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic interface
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract IERC721 is IERC165 {
              event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
              event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function balanceOf(address owner) public view returns (uint256 balance);
              function ownerOf(uint256 tokenId) public view returns (address owner);
          
              function approve(address to, uint256 tokenId) public;
              function getApproved(uint256 tokenId) public view returns (address operator);
          
              function setApprovalForAll(address operator, bool _approved) public;
              function isApprovedForAll(address owner, address operator) public view returns (bool);
          
              function transferFrom(address from, address to, uint256 tokenId) public;
              function safeTransferFrom(address from, address to, uint256 tokenId) public;
          
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: contracts/BaseRegistrar.sol
          
          pragma solidity >=0.4.24;
          
          
          
          
          
          contract BaseRegistrar is IERC721, Ownable {
              uint constant public GRACE_PERIOD = 90 days;
          
              event ControllerAdded(address indexed controller);
              event ControllerRemoved(address indexed controller);
              event NameMigrated(uint256 indexed id, address indexed owner, uint expires);
              event NameRegistered(uint256 indexed id, address indexed owner, uint expires);
              event NameRenewed(uint256 indexed id, uint expires);
          
              // Expiration timestamp for migrated domains.
              uint public transferPeriodEnds;
          
              // The ENS registry
              ENS public ens;
          
              // The namehash of the TLD this registrar owns (eg, .eth)
              bytes32 public baseNode;
          
              // The interim registrar
              Registrar public previousRegistrar;
          
              // A map of addresses that are authorised to register and renew names.
              mapping(address=>bool) public controllers;
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external;
          
              // Revoke controller permission for an address.
              function removeController(address controller) external;
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external;
          
              // Returns the expiration timestamp of the specified label hash.
              function nameExpires(uint256 id) external view returns(uint);
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool);
          
              /**
               * @dev Register a name.
               */
              function register(uint256 id, address owner, uint duration) external returns(uint);
          
              function renew(uint256 id, uint duration) external returns(uint);
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external;
          
              /**
               * @dev Transfers a registration from the initial registrar.
               * This function is called by the initial registrar when a user calls `transferRegistrars`.
               */
              function acceptRegistrarTransfer(bytes32 label, Deed deed, uint) external;
          }
          
          // File: contracts/StringUtils.sol
          
          pragma solidity >=0.4.24;
          
          library StringUtils {
              /**
               * @dev Returns the length of a given string
               *
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string memory s) internal pure returns (uint) {
                  uint len;
                  uint i = 0;
                  uint bytelength = bytes(s).length;
                  for(len = 0; i < bytelength; len++) {
                      byte b = bytes(s)[i];
                      if(b < 0x80) {
                          i += 1;
                      } else if (b < 0xE0) {
                          i += 2;
                      } else if (b < 0xF0) {
                          i += 3;
                      } else if (b < 0xF8) {
                          i += 4;
                      } else if (b < 0xFC) {
                          i += 5;
                      } else {
                          i += 6;
                      }
                  }
                  return len;
              }
          }
          
          // File: @ensdomains/resolver/contracts/Resolver.sol
          
          pragma solidity >=0.4.25;
          
          /**
           * A generic resolver interface which includes all the functions including the ones deprecated
           */
          interface Resolver{
              event AddrChanged(bytes32 indexed node, address a);
              event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);
              event NameChanged(bytes32 indexed node, string name);
              event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
              event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
              event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
              event ContenthashChanged(bytes32 indexed node, bytes hash);
              /* Deprecated events */
              event ContentChanged(bytes32 indexed node, bytes32 hash);
          
              function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);
              function addr(bytes32 node) external view returns (address);
              function addr(bytes32 node, uint coinType) external view returns(bytes memory);
              function contenthash(bytes32 node) external view returns (bytes memory);
              function dnsrr(bytes32 node) external view returns (bytes memory);
              function name(bytes32 node) external view returns (string memory);
              function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);
              function text(bytes32 node, string calldata key) external view returns (string memory);
              function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
          
              function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;
              function setAddr(bytes32 node, address addr) external;
              function setAddr(bytes32 node, uint coinType, bytes calldata a) external;
              function setContenthash(bytes32 node, bytes calldata hash) external;
              function setDnsrr(bytes32 node, bytes calldata data) external;
              function setName(bytes32 node, string calldata _name) external;
              function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;
              function setText(bytes32 node, string calldata key, string calldata value) external;
              function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;
          
              function supportsInterface(bytes4 interfaceID) external pure returns (bool);
          
              /* Deprecated functions */
              function content(bytes32 node) external view returns (bytes32);
              function multihash(bytes32 node) external view returns (bytes memory);
              function setContent(bytes32 node, bytes32 hash) external;
              function setMultihash(bytes32 node, bytes calldata hash) external;
          }
          
          // File: contracts/ETHRegistrarController.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          
          /**
           * @dev A registrar controller for registering and renewing names at fixed cost.
           */
          contract ETHRegistrarController is Ownable {
              using StringUtils for *;
          
              uint constant public MIN_REGISTRATION_DURATION = 28 days;
          
              bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
              bytes4 constant private COMMITMENT_CONTROLLER_ID = bytes4(
                  keccak256("rentPrice(string,uint256)") ^
                  keccak256("available(string)") ^
                  keccak256("makeCommitment(string,address,bytes32)") ^
                  keccak256("commit(bytes32)") ^
                  keccak256("register(string,address,uint256,bytes32)") ^
                  keccak256("renew(string,uint256)")
              );
          
              bytes4 constant private COMMITMENT_WITH_CONFIG_CONTROLLER_ID = bytes4(
                  keccak256("registerWithConfig(string,address,uint256,bytes32,address,address)") ^
                  keccak256("makeCommitmentWithConfig(string,address,bytes32,address,address)")
              );
          
              BaseRegistrar base;
              PriceOracle prices;
              uint public minCommitmentAge;
              uint public maxCommitmentAge;
          
              mapping(bytes32=>uint) public commitments;
          
              event NameRegistered(string name, bytes32 indexed label, address indexed owner, uint cost, uint expires);
              event NameRenewed(string name, bytes32 indexed label, uint cost, uint expires);
              event NewPriceOracle(address indexed oracle);
          
              constructor(BaseRegistrar _base, PriceOracle _prices, uint _minCommitmentAge, uint _maxCommitmentAge) public {
                  require(_maxCommitmentAge > _minCommitmentAge);
          
                  base = _base;
                  prices = _prices;
                  minCommitmentAge = _minCommitmentAge;
                  maxCommitmentAge = _maxCommitmentAge;
              }
          
              function rentPrice(string memory name, uint duration) view public returns(uint) {
                  bytes32 hash = keccak256(bytes(name));
                  return prices.price(name, base.nameExpires(uint256(hash)), duration);
              }
          
              function valid(string memory name) public pure returns(bool) {
                  return name.strlen() >= 3;
              }
          
              function available(string memory name) public view returns(bool) {
                  bytes32 label = keccak256(bytes(name));
                  return valid(name) && base.available(uint256(label));
              }
          
              function makeCommitment(string memory name, address owner, bytes32 secret) pure public returns(bytes32) {
                  return makeCommitmentWithConfig(name, owner, secret, address(0), address(0));
              }
          
              function makeCommitmentWithConfig(string memory name, address owner, bytes32 secret, address resolver, address addr) pure public returns(bytes32) {
                  bytes32 label = keccak256(bytes(name));
                  if (resolver == address(0) && addr == address(0)) {
                      return keccak256(abi.encodePacked(label, owner, secret));
                  }
                  require(resolver != address(0));
                  return keccak256(abi.encodePacked(label, owner, resolver, addr, secret));
              }
          
              function commit(bytes32 commitment) public {
                  require(commitments[commitment] + maxCommitmentAge < now);
                  commitments[commitment] = now;
              }
          
              function register(string calldata name, address owner, uint duration, bytes32 secret) external payable {
                registerWithConfig(name, owner, duration, secret, address(0), address(0));
              }
          
              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);
          
                  bytes32 label = keccak256(bytes(name));
                  uint256 tokenId = uint256(label);
          
                  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);
          
                      // The nodehash of this label
                      bytes32 nodehash = keccak256(abi.encodePacked(base.baseNode(), label));
          
                      // Set the resolver
                      base.ens().setResolver(nodehash, resolver);
          
                      // Configure the resolver
                      if (addr != address(0)) {
                          Resolver(resolver).setAddr(nodehash, addr);
                      }
          
                      // Now transfer full ownership to the expeceted owner
                      base.transferFrom(address(this), owner, tokenId);
                  } 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);
                  }
              }
          
              function renew(string calldata name, uint duration) external payable {
                  uint cost = rentPrice(name, duration);
                  require(msg.value >= cost);
          
                  bytes32 label = keccak256(bytes(name));
                  uint expires = base.renew(uint256(label), duration);
          
                  if(msg.value > cost) {
                      msg.sender.transfer(msg.value - cost);
                  }
          
                  emit NameRenewed(name, label, cost, expires);
              }
          
              function setPriceOracle(PriceOracle _prices) public onlyOwner {
                  prices = _prices;
                  emit NewPriceOracle(address(prices));
              }
          
              function setCommitmentAges(uint _minCommitmentAge, uint _maxCommitmentAge) public onlyOwner {
                  minCommitmentAge = _minCommitmentAge;
                  maxCommitmentAge = _maxCommitmentAge;
              }
          
              function withdraw() public onlyOwner {
                  msg.sender.transfer(address(this).balance);
              }
          
              function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
                  return interfaceID == INTERFACE_META_ID ||
                         interfaceID == COMMITMENT_CONTROLLER_ID ||
                         interfaceID == COMMITMENT_WITH_CONFIG_CONTROLLER_ID;
              }
          
              function _consumeCommitment(string memory name, uint duration, bytes32 commitment) internal returns (uint256) {
                  // Require a valid commitment
                  require(commitments[commitment] + minCommitmentAge <= now);
          
                  // If the commitment is too old, or the name is registered, stop
                  require(commitments[commitment] + maxCommitmentAge > now);
                  require(available(name));
          
                  delete(commitments[commitment]);
          
                  uint cost = rentPrice(name, duration);
                  require(duration >= MIN_REGISTRATION_DURATION);
                  require(msg.value >= cost);
          
                  return cost;
              }
          }

          File 2 of 6: BaseRegistrarImplementation
          // File: @ensdomains/ens/contracts/ENS.sol
          
          pragma solidity >=0.4.24;
          
          interface ENS {
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          
          
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external;
              function setResolver(bytes32 node, address resolver) external;
              function setOwner(bytes32 node, address owner) external;
              function setTTL(bytes32 node, uint64 ttl) external;
              function owner(bytes32 node) external view returns (address);
              function resolver(bytes32 node) external view returns (address);
              function ttl(bytes32 node) external view returns (uint64);
          
          }
          
          // File: @ensdomains/ens/contracts/Deed.sol
          
          pragma solidity >=0.4.24;
          
          interface Deed {
          
              function setOwner(address payable newOwner) external;
              function setRegistrar(address newRegistrar) external;
              function setBalance(uint newValue, bool throwOnFailure) external;
              function closeDeed(uint refundRatio) external;
              function destroyDeed() external;
          
              function owner() external view returns (address);
              function previousOwner() external view returns (address);
              function value() external view returns (uint);
              function creationDate() external view returns (uint);
          
          }
          
          // File: @ensdomains/ens/contracts/Registrar.sol
          
          pragma solidity >=0.4.24;
          
          
          interface Registrar {
          
              enum Mode { Open, Auction, Owned, Forbidden, Reveal, NotYetAvailable }
          
              event AuctionStarted(bytes32 indexed hash, uint registrationDate);
              event NewBid(bytes32 indexed hash, address indexed bidder, uint deposit);
              event BidRevealed(bytes32 indexed hash, address indexed owner, uint value, uint8 status);
              event HashRegistered(bytes32 indexed hash, address indexed owner, uint value, uint registrationDate);
              event HashReleased(bytes32 indexed hash, uint value);
              event HashInvalidated(bytes32 indexed hash, string indexed name, uint value, uint registrationDate);
          
              function startAuction(bytes32 _hash) external;
              function startAuctions(bytes32[] calldata _hashes) external;
              function newBid(bytes32 sealedBid) external payable;
              function startAuctionsAndBid(bytes32[] calldata hashes, bytes32 sealedBid) external payable;
              function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) external;
              function cancelBid(address bidder, bytes32 seal) external;
              function finalizeAuction(bytes32 _hash) external;
              function transfer(bytes32 _hash, address payable newOwner) external;
              function releaseDeed(bytes32 _hash) external;
              function invalidateName(string calldata unhashedName) external;
              function eraseNode(bytes32[] calldata labels) external;
              function transferRegistrars(bytes32 _hash) external;
              function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) external;
              function entries(bytes32 _hash) external view returns (Mode, address, uint, uint, uint);
          }
          
          // File: @ensdomains/ens/contracts/DeedImplementation.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title Deed to hold ether in exchange for ownership of a node
           * @dev The deed can be controlled only by the registrar and can only send ether back to the owner.
           */
          contract DeedImplementation is Deed {
          
              address payable constant burn = address(0xdead);
          
              address payable private _owner;
              address private _previousOwner;
              address private _registrar;
          
              uint private _creationDate;
              uint private _value;
          
              bool active;
          
              event OwnerChanged(address newOwner);
              event DeedClosed();
          
              modifier onlyRegistrar {
                  require(msg.sender == _registrar);
                  _;
              }
          
              modifier onlyActive {
                  require(active);
                  _;
              }
          
              constructor(address payable initialOwner) public payable {
                  _owner = initialOwner;
                  _registrar = msg.sender;
                  _creationDate = now;
                  active = true;
                  _value = msg.value;
              }
          
              function setOwner(address payable newOwner) external onlyRegistrar {
                  require(newOwner != address(0x0));
                  _previousOwner = _owner;  // This allows contracts to check who sent them the ownership
                  _owner = newOwner;
                  emit OwnerChanged(newOwner);
              }
          
              function setRegistrar(address newRegistrar) external onlyRegistrar {
                  _registrar = newRegistrar;
              }
          
              function setBalance(uint newValue, bool throwOnFailure) external onlyRegistrar onlyActive {
                  // Check if it has enough balance to set the value
                  require(_value >= newValue);
                  _value = newValue;
                  // Send the difference to the owner
                  require(_owner.send(address(this).balance - newValue) || !throwOnFailure);
              }
          
              /**
               * @dev Close a deed and refund a specified fraction of the bid value
               *
               * @param refundRatio The amount*1/1000 to refund
               */
              function closeDeed(uint refundRatio) external onlyRegistrar onlyActive {
                  active = false;
                  require(burn.send(((1000 - refundRatio) * address(this).balance)/1000));
                  emit DeedClosed();
                  _destroyDeed();
              }
          
              /**
               * @dev Close a deed and refund a specified fraction of the bid value
               */
              function destroyDeed() external {
                  _destroyDeed();
              }
          
              function owner() external view returns (address) {
                  return _owner;
              }
          
              function previousOwner() external view returns (address) {
                  return _previousOwner;
              }
          
              function value() external view returns (uint) {
                  return _value;
              }
          
              function creationDate() external view returns (uint) {
                  _creationDate;
              }
          
              function _destroyDeed() internal {
                  require(!active);
          
                  // Instead of selfdestruct(owner), invoke owner fallback function to allow
                  // owner to log an event if desired; but owner should also be aware that
                  // its fallback function can also be invoked by setBalance
                  if (_owner.send(address(this).balance)) {
                      selfdestruct(burn);
                  }
              }
          }
          
          // File: @ensdomains/ens/contracts/HashRegistrar.sol
          
          pragma solidity ^0.5.0;
          
          
          /*
          
          Temporary Hash Registrar
          ========================
          
          This is a simplified version of a hash registrar. It is purporsefully limited:
          names cannot be six letters or shorter, new auctions will stop after 4 years.
          
          The plan is to test the basic features and then move to a new contract in at most
          2 years, when some sort of renewal mechanism will be enabled.
          */
          
          
          
          
          /**
           * @title Registrar
           * @dev The registrar handles the auction process for each subnode of the node it owns.
           */
          contract HashRegistrar is Registrar {
              ENS public ens;
              bytes32 public rootNode;
          
              mapping (bytes32 => Entry) _entries;
              mapping (address => mapping (bytes32 => Deed)) public sealedBids;
          
              uint32 constant totalAuctionLength = 5 days;
              uint32 constant revealPeriod = 48 hours;
              uint32 public constant launchLength = 8 weeks;
          
              uint constant minPrice = 0.01 ether;
              uint public registryStarted;
          
              struct Entry {
                  Deed deed;
                  uint registrationDate;
                  uint value;
                  uint highestBid;
              }
          
              modifier inState(bytes32 _hash, Mode _state) {
                  require(state(_hash) == _state);
                  _;
              }
          
              modifier onlyOwner(bytes32 _hash) {
                  require(state(_hash) == Mode.Owned && msg.sender == _entries[_hash].deed.owner());
                  _;
              }
          
              modifier registryOpen() {
                  require(now >= registryStarted && now <= registryStarted + (365 * 4) * 1 days && ens.owner(rootNode) == address(this));
                  _;
              }
          
              /**
               * @dev Constructs a new Registrar, with the provided address as the owner of the root node.
               *
               * @param _ens The address of the ENS
               * @param _rootNode The hash of the rootnode.
               */
              constructor(ENS _ens, bytes32 _rootNode, uint _startDate) public {
                  ens = _ens;
                  rootNode = _rootNode;
                  registryStarted = _startDate > 0 ? _startDate : now;
              }
          
              /**
               * @dev Start an auction for an available hash
               *
               * @param _hash The hash to start an auction on
               */
              function startAuction(bytes32 _hash) external {
                  _startAuction(_hash);
              }
          
              /**
               * @dev Start multiple auctions for better anonymity
               *
               * Anyone can start an auction by sending an array of hashes that they want to bid for.
               * Arrays are sent so that someone can open up an auction for X dummy hashes when they
               * are only really interested in bidding for one. This will increase the cost for an
               * attacker to simply bid blindly on all new auctions. Dummy auctions that are
               * open but not bid on are closed after a week.
               *
               * @param _hashes An array of hashes, at least one of which you presumably want to bid on
               */
              function startAuctions(bytes32[] calldata _hashes) external {
                  _startAuctions(_hashes);
              }
          
              /**
               * @dev Submit a new sealed bid on a desired hash in a blind auction
               *
               * Bids are sent by sending a message to the main contract with a hash and an amount. The hash
               * contains information about the bid, including the bidded hash, the bid amount, and a random
               * salt. Bids are not tied to any one auction until they are revealed. The value of the bid
               * itself can be masqueraded by sending more than the value of your actual bid. This is
               * followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable.
               * Since this is an auction, it is expected that most public hashes, like known domains and common dictionary
               * words, will have multiple bidders pushing the price up.
               *
               * @param sealedBid A sealedBid, created by the shaBid function
               */
              function newBid(bytes32 sealedBid) external payable {
                  _newBid(sealedBid);
              }
          
              /**
               * @dev Start a set of auctions and bid on one of them
               *
               * This method functions identically to calling `startAuctions` followed by `newBid`,
               * but all in one transaction.
               *
               * @param hashes A list of hashes to start auctions on.
               * @param sealedBid A sealed bid for one of the auctions.
               */
              function startAuctionsAndBid(bytes32[] calldata hashes, bytes32 sealedBid) external payable {
                  _startAuctions(hashes);
                  _newBid(sealedBid);
              }
          
              /**
               * @dev Submit the properties of a bid to reveal them
               *
               * @param _hash The node in the sealedBid
               * @param _value The bid amount in the sealedBid
               * @param _salt The sale in the sealedBid
               */
              function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) external {
                  bytes32 seal = shaBid(_hash, msg.sender, _value, _salt);
                  Deed bid = sealedBids[msg.sender][seal];
                  require(address(bid) != address(0x0));
          
                  sealedBids[msg.sender][seal] = Deed(address(0x0));
                  Entry storage h = _entries[_hash];
                  uint value = min(_value, bid.value());
                  bid.setBalance(value, true);
          
                  Mode auctionState = state(_hash);
                  if (auctionState == Mode.Owned) {
                      // Too late! Bidder loses their bid. Gets 0.5% back.
                      bid.closeDeed(5);
                      emit BidRevealed(_hash, msg.sender, value, 1);
                  } else if (auctionState != Mode.Reveal) {
                      // Invalid phase
                      revert();
                  } else if (value < minPrice || bid.creationDate() > h.registrationDate - revealPeriod) {
                      // Bid too low or too late, refund 99.5%
                      bid.closeDeed(995);
                      emit BidRevealed(_hash, msg.sender, value, 0);
                  } else if (value > h.highestBid) {
                      // New winner
                      // Cancel the other bid, refund 99.5%
                      if (address(h.deed) != address(0x0)) {
                          Deed previousWinner = h.deed;
                          previousWinner.closeDeed(995);
                      }
          
                      // Set new winner
                      // Per the rules of a vickery auction, the value becomes the previous highestBid
                      h.value = h.highestBid;  // will be zero if there's only 1 bidder
                      h.highestBid = value;
                      h.deed = bid;
                      emit BidRevealed(_hash, msg.sender, value, 2);
                  } else if (value > h.value) {
                      // Not winner, but affects second place
                      h.value = value;
                      bid.closeDeed(995);
                      emit BidRevealed(_hash, msg.sender, value, 3);
                  } else {
                      // Bid doesn't affect auction
                      bid.closeDeed(995);
                      emit BidRevealed(_hash, msg.sender, value, 4);
                  }
              }
          
              /**
               * @dev Cancel a bid
               *
               * @param seal The value returned by the shaBid function
               */
              function cancelBid(address bidder, bytes32 seal) external {
                  Deed bid = sealedBids[bidder][seal];
                  
                  // If a sole bidder does not `unsealBid` in time, they have a few more days
                  // where they can call `startAuction` (again) and then `unsealBid` during
                  // the revealPeriod to get back their bid value.
                  // For simplicity, they should call `startAuction` within
                  // 9 days (2 weeks - totalAuctionLength), otherwise their bid will be
                  // cancellable by anyone.
                  require(address(bid) != address(0x0) && now >= bid.creationDate() + totalAuctionLength + 2 weeks);
          
                  // Send the canceller 0.5% of the bid, and burn the rest.
                  bid.setOwner(msg.sender);
                  bid.closeDeed(5);
                  sealedBids[bidder][seal] = Deed(0);
                  emit BidRevealed(seal, bidder, 0, 5);
              }
          
              /**
               * @dev Finalize an auction after the registration date has passed
               *
               * @param _hash The hash of the name the auction is for
               */
              function finalizeAuction(bytes32 _hash) external onlyOwner(_hash) {
                  Entry storage h = _entries[_hash];
                  
                  // Handles the case when there's only a single bidder (h.value is zero)
                  h.value = max(h.value, minPrice);
                  h.deed.setBalance(h.value, true);
          
                  trySetSubnodeOwner(_hash, h.deed.owner());
                  emit HashRegistered(_hash, h.deed.owner(), h.value, h.registrationDate);
              }
          
              /**
               * @dev The owner of a domain may transfer it to someone else at any time.
               *
               * @param _hash The node to transfer
               * @param newOwner The address to transfer ownership to
               */
              function transfer(bytes32 _hash, address payable newOwner) external onlyOwner(_hash) {
                  require(newOwner != address(0x0));
          
                  Entry storage h = _entries[_hash];
                  h.deed.setOwner(newOwner);
                  trySetSubnodeOwner(_hash, newOwner);
              }
          
              /**
               * @dev After some time, or if we're no longer the registrar, the owner can release
               *      the name and get their ether back.
               *
               * @param _hash The node to release
               */
              function releaseDeed(bytes32 _hash) external onlyOwner(_hash) {
                  Entry storage h = _entries[_hash];
                  Deed deedContract = h.deed;
          
                  require(now >= h.registrationDate + 365 days || ens.owner(rootNode) != address(this));
          
                  h.value = 0;
                  h.highestBid = 0;
                  h.deed = Deed(0);
          
                  _tryEraseSingleNode(_hash);
                  deedContract.closeDeed(1000);
                  emit HashReleased(_hash, h.value);        
              }
          
              /**
               * @dev Submit a name 6 characters long or less. If it has been registered,
               *      the submitter will earn 50% of the deed value. 
               * 
               * We are purposefully handicapping the simplified registrar as a way 
               * to force it into being restructured in a few years.
               *
               * @param unhashedName An invalid name to search for in the registry.
               */
              function invalidateName(string calldata unhashedName)
                  external
                  inState(keccak256(abi.encode(unhashedName)), Mode.Owned)
              {
                  require(strlen(unhashedName) <= 6);
                  bytes32 hash = keccak256(abi.encode(unhashedName));
          
                  Entry storage h = _entries[hash];
          
                  _tryEraseSingleNode(hash);
          
                  if (address(h.deed) != address(0x0)) {
                      // Reward the discoverer with 50% of the deed
                      // The previous owner gets 50%
                      h.value = max(h.value, minPrice);
                      h.deed.setBalance(h.value/2, false);
                      h.deed.setOwner(msg.sender);
                      h.deed.closeDeed(1000);
                  }
          
                  emit HashInvalidated(hash, unhashedName, h.value, h.registrationDate);
          
                  h.value = 0;
                  h.highestBid = 0;
                  h.deed = Deed(0);
              }
          
              /**
               * @dev Allows anyone to delete the owner and resolver records for a (subdomain of) a
               *      name that is not currently owned in the registrar. If passing, eg, 'foo.bar.eth',
               *      the owner and resolver fields on 'foo.bar.eth' and 'bar.eth' will all be cleared.
               *
               * @param labels A series of label hashes identifying the name to zero out, rooted at the
               *        registrar's root. Must contain at least one element. For instance, to zero 
               *        'foo.bar.eth' on a registrar that owns '.eth', pass an array containing
               *        [keccak256('foo'), keccak256('bar')].
               */
              function eraseNode(bytes32[] calldata labels) external {
                  require(labels.length != 0);
                  require(state(labels[labels.length - 1]) != Mode.Owned);
          
                  _eraseNodeHierarchy(labels.length - 1, labels, rootNode);
              }
          
              /**
               * @dev Transfers the deed to the current registrar, if different from this one.
               *
               * Used during the upgrade process to a permanent registrar.
               *
               * @param _hash The name hash to transfer.
               */
              function transferRegistrars(bytes32 _hash) external onlyOwner(_hash) {
                  address registrar = ens.owner(rootNode);
                  require(registrar != address(this));
          
                  // Migrate the deed
                  Entry storage h = _entries[_hash];
                  h.deed.setRegistrar(registrar);
          
                  // Call the new registrar to accept the transfer
                  Registrar(registrar).acceptRegistrarTransfer(_hash, h.deed, h.registrationDate);
          
                  // Zero out the Entry
                  h.deed = Deed(0);
                  h.registrationDate = 0;
                  h.value = 0;
                  h.highestBid = 0;
              }
          
              /**
               * @dev Accepts a transfer from a previous registrar; stubbed out here since there
               *      is no previous registrar implementing this interface.
               *
               * @param hash The sha3 hash of the label to transfer.
               * @param deed The Deed object for the name being transferred in.
               * @param registrationDate The date at which the name was originally registered.
               */
              function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) external {
                  hash; deed; registrationDate; // Don't warn about unused variables
              }
          
              function entries(bytes32 _hash) external view returns (Mode, address, uint, uint, uint) {
                  Entry storage h = _entries[_hash];
                  return (state(_hash), address(h.deed), h.registrationDate, h.value, h.highestBid);
              }
          
              // State transitions for names:
              //   Open -> Auction (startAuction)
              //   Auction -> Reveal
              //   Reveal -> Owned
              //   Reveal -> Open (if nobody bid)
              //   Owned -> Open (releaseDeed or invalidateName)
              function state(bytes32 _hash) public view returns (Mode) {
                  Entry storage entry = _entries[_hash];
          
                  if (!isAllowed(_hash, now)) {
                      return Mode.NotYetAvailable;
                  } else if (now < entry.registrationDate) {
                      if (now < entry.registrationDate - revealPeriod) {
                          return Mode.Auction;
                      } else {
                          return Mode.Reveal;
                      }
                  } else {
                      if (entry.highestBid == 0) {
                          return Mode.Open;
                      } else {
                          return Mode.Owned;
                      }
                  }
              }
          
              /**
               * @dev Determines if a name is available for registration yet
               *
               * Each name will be assigned a random date in which its auction
               * can be started, from 0 to 8 weeks
               *
               * @param _hash The hash to start an auction on
               * @param _timestamp The timestamp to query about
               */
              function isAllowed(bytes32 _hash, uint _timestamp) public view returns (bool allowed) {
                  return _timestamp > getAllowedTime(_hash);
              }
          
              /**
               * @dev Returns available date for hash
               *
               * The available time from the `registryStarted` for a hash is proportional
               * to its numeric value.
               *
               * @param _hash The hash to start an auction on
               */
              function getAllowedTime(bytes32 _hash) public view returns (uint) {
                  return registryStarted + ((launchLength * (uint(_hash) >> 128)) >> 128);
                  // Right shift operator: a >> b == a / 2**b
              }
          
              /**
               * @dev Hash the values required for a secret bid
               *
               * @param hash The node corresponding to the desired namehash
               * @param value The bid amount
               * @param salt A random value to ensure secrecy of the bid
               * @return The hash of the bid values
               */
              function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) public pure returns (bytes32) {
                  return keccak256(abi.encodePacked(hash, owner, value, salt));
              }
          
              function _tryEraseSingleNode(bytes32 label) internal {
                  if (ens.owner(rootNode) == address(this)) {
                      ens.setSubnodeOwner(rootNode, label, address(this));
                      bytes32 node = keccak256(abi.encodePacked(rootNode, label));
                      ens.setResolver(node, address(0x0));
                      ens.setOwner(node, address(0x0));
                  }
              }
          
              function _startAuction(bytes32 _hash) internal registryOpen() {
                  Mode mode = state(_hash);
                  if (mode == Mode.Auction) return;
                  require(mode == Mode.Open);
          
                  Entry storage newAuction = _entries[_hash];
                  newAuction.registrationDate = now + totalAuctionLength;
                  newAuction.value = 0;
                  newAuction.highestBid = 0;
                  emit AuctionStarted(_hash, newAuction.registrationDate);
              }
          
              function _startAuctions(bytes32[] memory _hashes) internal {
                  for (uint i = 0; i < _hashes.length; i ++) {
                      _startAuction(_hashes[i]);
                  }
              }
          
              function _newBid(bytes32 sealedBid) internal {
                  require(address(sealedBids[msg.sender][sealedBid]) == address(0x0));
                  require(msg.value >= minPrice);
          
                  // Creates a new hash contract with the owner
                  Deed bid = (new DeedImplementation).value(msg.value)(msg.sender);
                  sealedBids[msg.sender][sealedBid] = bid;
                  emit NewBid(sealedBid, msg.sender, msg.value);
              }
          
              function _eraseNodeHierarchy(uint idx, bytes32[] memory labels, bytes32 node) internal {
                  // Take ownership of the node
                  ens.setSubnodeOwner(node, labels[idx], address(this));
                  node = keccak256(abi.encodePacked(node, labels[idx]));
          
                  // Recurse if there are more labels
                  if (idx > 0) {
                      _eraseNodeHierarchy(idx - 1, labels, node);
                  }
          
                  // Erase the resolver and owner records
                  ens.setResolver(node, address(0x0));
                  ens.setOwner(node, address(0x0));
              }
          
              /**
               * @dev Assign the owner in ENS, if we're still the registrar
               *
               * @param _hash hash to change owner
               * @param _newOwner new owner to transfer to
               */
              function trySetSubnodeOwner(bytes32 _hash, address _newOwner) internal {
                  if (ens.owner(rootNode) == address(this))
                      ens.setSubnodeOwner(rootNode, _hash, _newOwner);
              }
          
              /**
               * @dev Returns the maximum of two unsigned integers
               *
               * @param a A number to compare
               * @param b A number to compare
               * @return The maximum of two unsigned integers
               */
              function max(uint a, uint b) internal pure returns (uint) {
                  if (a > b)
                      return a;
                  else
                      return b;
              }
          
              /**
               * @dev Returns the minimum of two unsigned integers
               *
               * @param a A number to compare
               * @param b A number to compare
               * @return The minimum of two unsigned integers
               */
              function min(uint a, uint b) internal pure returns (uint) {
                  if (a < b)
                      return a;
                  else
                      return b;
              }
          
              /**
               * @dev Returns the length of a given string
               *
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string memory s) internal pure returns (uint) {
                  s; // Don't warn about unused variables
                  // Starting here means the LSB will be the byte we care about
                  uint ptr;
                  uint end;
                  assembly {
                      ptr := add(s, 1)
                      end := add(mload(s), ptr)
                  }
                  uint len = 0;
                  for (len; ptr < end; len++) {
                      uint8 b;
                      assembly { b := and(mload(ptr), 0xFF) }
                      if (b < 0x80) {
                          ptr += 1;
                      } else if (b < 0xE0) {
                          ptr += 2;
                      } else if (b < 0xF0) {
                          ptr += 3;
                      } else if (b < 0xF8) {
                          ptr += 4;
                      } else if (b < 0xFC) {
                          ptr += 5;
                      } else {
                          ptr += 6;
                      }
                  }
                  return len;
              }
          
          }
          
          // File: openzeppelin-solidity/contracts/introspection/IERC165.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title IERC165
           * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
           */
          interface IERC165 {
              /**
               * @notice Query if a contract implements an interface
               * @param interfaceId The interface identifier, as specified in ERC-165
               * @dev Interface identification is specified in ERC-165. This function
               * uses less than 30,000 gas.
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool);
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic interface
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract IERC721 is IERC165 {
              event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
              event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
              event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
          
              function balanceOf(address owner) public view returns (uint256 balance);
              function ownerOf(uint256 tokenId) public view returns (address owner);
          
              function approve(address to, uint256 tokenId) public;
              function getApproved(uint256 tokenId) public view returns (address operator);
          
              function setApprovalForAll(address operator, bool _approved) public;
              function isApprovedForAll(address owner, address operator) public view returns (bool);
          
              function transferFrom(address from, address to, uint256 tokenId) public;
              function safeTransferFrom(address from, address to, uint256 tokenId) public;
          
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title ERC721 token receiver interface
           * @dev Interface for any contract that wants to support safeTransfers
           * from ERC721 asset contracts.
           */
          contract IERC721Receiver {
              /**
               * @notice Handle the receipt of an NFT
               * @dev The ERC721 smart contract calls this function on the recipient
               * after a `safeTransfer`. This function MUST return the function selector,
               * otherwise the caller will revert the transaction. The selector to be
               * returned can be obtained as `this.onERC721Received.selector`. This
               * function MAY throw to revert and reject the transfer.
               * Note: the ERC721 contract address is always the message sender.
               * @param operator The address which called `safeTransferFrom` function
               * @param from The address which previously owned the token
               * @param tokenId The NFT identifier which is being transferred
               * @param data Additional data with no specified format
               * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
               */
              function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
              public returns (bytes4);
          }
          
          // File: openzeppelin-solidity/contracts/math/SafeMath.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title SafeMath
           * @dev Unsigned math operations with safety checks that revert on error
           */
          library SafeMath {
              /**
              * @dev Multiplies two unsigned integers, reverts on overflow.
              */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
          
                  uint256 c = a * b;
                  require(c / a == b);
          
                  return c;
              }
          
              /**
              * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
              */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Solidity only automatically asserts when dividing by 0
                  require(b > 0);
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
              * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
          
                  return c;
              }
          
              /**
              * @dev Adds two unsigned integers, reverts on overflow.
              */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
          
                  return c;
              }
          
              /**
              * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
              * reverts when dividing by zero.
              */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0);
                  return a % b;
              }
          }
          
          // File: openzeppelin-solidity/contracts/utils/Address.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * Utility library of inline functions on addresses
           */
          library Address {
              /**
               * Returns whether the target address is a contract
               * @dev This function will return false if invoked during the constructor of a contract,
               * as the code is not actually created until after the constructor finishes.
               * @param account address of the account to check
               * @return whether the target address is a contract
               */
              function isContract(address account) internal view returns (bool) {
                  uint256 size;
                  // XXX Currently there is no better way to check if there is a contract in an address
                  // than to check the size of the code at that address.
                  // See https://ethereum.stackexchange.com/a/14016/36603
                  // for more details about how this works.
                  // TODO Check this again before the Serenity release, because all addresses will be
                  // contracts then.
                  // solhint-disable-next-line no-inline-assembly
                  assembly { size := extcodesize(account) }
                  return size > 0;
              }
          }
          
          // File: openzeppelin-solidity/contracts/introspection/ERC165.sol
          
          pragma solidity ^0.5.0;
          
          
          /**
           * @title ERC165
           * @author Matt Condon (@shrugs)
           * @dev Implements ERC165 using a lookup table.
           */
          contract ERC165 is IERC165 {
              bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
              /**
               * 0x01ffc9a7 ===
               *     bytes4(keccak256('supportsInterface(bytes4)'))
               */
          
              /**
               * @dev a mapping of interface id to whether or not it's supported
               */
              mapping(bytes4 => bool) private _supportedInterfaces;
          
              /**
               * @dev A contract implementing SupportsInterfaceWithLookup
               * implement ERC165 itself
               */
              constructor () internal {
                  _registerInterface(_INTERFACE_ID_ERC165);
              }
          
              /**
               * @dev implement supportsInterface(bytes4) using a lookup table
               */
              function supportsInterface(bytes4 interfaceId) external view returns (bool) {
                  return _supportedInterfaces[interfaceId];
              }
          
              /**
               * @dev internal method for registering an interface
               */
              function _registerInterface(bytes4 interfaceId) internal {
                  require(interfaceId != 0xffffffff);
                  _supportedInterfaces[interfaceId] = true;
              }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC721/ERC721.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          
          /**
           * @title ERC721 Non-Fungible Token Standard basic implementation
           * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
           */
          contract ERC721 is ERC165, IERC721 {
              using SafeMath for uint256;
              using Address for address;
          
              // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
              // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
              bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
          
              // Mapping from token ID to owner
              mapping (uint256 => address) private _tokenOwner;
          
              // Mapping from token ID to approved address
              mapping (uint256 => address) private _tokenApprovals;
          
              // Mapping from owner to number of owned token
              mapping (address => uint256) private _ownedTokensCount;
          
              // Mapping from owner to operator approvals
              mapping (address => mapping (address => bool)) private _operatorApprovals;
          
              bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
              /*
               * 0x80ac58cd ===
               *     bytes4(keccak256('balanceOf(address)')) ^
               *     bytes4(keccak256('ownerOf(uint256)')) ^
               *     bytes4(keccak256('approve(address,uint256)')) ^
               *     bytes4(keccak256('getApproved(uint256)')) ^
               *     bytes4(keccak256('setApprovalForAll(address,bool)')) ^
               *     bytes4(keccak256('isApprovedForAll(address,address)')) ^
               *     bytes4(keccak256('transferFrom(address,address,uint256)')) ^
               *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
               *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
               */
          
              constructor () public {
                  // register the supported interfaces to conform to ERC721 via ERC165
                  _registerInterface(_INTERFACE_ID_ERC721);
              }
          
              /**
               * @dev Gets the balance of the specified address
               * @param owner address to query the balance of
               * @return uint256 representing the amount owned by the passed address
               */
              function balanceOf(address owner) public view returns (uint256) {
                  require(owner != address(0));
                  return _ownedTokensCount[owner];
              }
          
              /**
               * @dev Gets the owner of the specified token ID
               * @param tokenId uint256 ID of the token to query the owner of
               * @return owner address currently marked as the owner of the given token ID
               */
              function ownerOf(uint256 tokenId) public view returns (address) {
                  address owner = _tokenOwner[tokenId];
                  require(owner != address(0));
                  return owner;
              }
          
              /**
               * @dev Approves another address to transfer the given token ID
               * The zero address indicates there is no approved address.
               * There can only be one approved address per token at a given time.
               * Can only be called by the token owner or an approved operator.
               * @param to address to be approved for the given token ID
               * @param tokenId uint256 ID of the token to be approved
               */
              function approve(address to, uint256 tokenId) public {
                  address owner = ownerOf(tokenId);
                  require(to != owner);
                  require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
          
                  _tokenApprovals[tokenId] = to;
                  emit Approval(owner, to, tokenId);
              }
          
              /**
               * @dev Gets the approved address for a token ID, or zero if no address set
               * Reverts if the token ID does not exist.
               * @param tokenId uint256 ID of the token to query the approval of
               * @return address currently approved for the given token ID
               */
              function getApproved(uint256 tokenId) public view returns (address) {
                  require(_exists(tokenId));
                  return _tokenApprovals[tokenId];
              }
          
              /**
               * @dev Sets or unsets the approval of a given operator
               * An operator is allowed to transfer all tokens of the sender on their behalf
               * @param to operator address to set the approval
               * @param approved representing the status of the approval to be set
               */
              function setApprovalForAll(address to, bool approved) public {
                  require(to != msg.sender);
                  _operatorApprovals[msg.sender][to] = approved;
                  emit ApprovalForAll(msg.sender, to, approved);
              }
          
              /**
               * @dev Tells whether an operator is approved by a given owner
               * @param owner owner address which you want to query the approval of
               * @param operator operator address which you want to query the approval of
               * @return bool whether the given operator is approved by the given owner
               */
              function isApprovedForAll(address owner, address operator) public view returns (bool) {
                  return _operatorApprovals[owner][operator];
              }
          
              /**
               * @dev Transfers the ownership of a given token ID to another address
               * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function transferFrom(address from, address to, uint256 tokenId) public {
                  require(_isApprovedOrOwner(msg.sender, tokenId));
          
                  _transferFrom(from, to, tokenId);
              }
          
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               *
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function safeTransferFrom(address from, address to, uint256 tokenId) public {
                  safeTransferFrom(from, to, tokenId, "");
              }
          
              /**
               * @dev Safely transfers the ownership of a given token ID to another address
               * If the target address is a contract, it must implement `onERC721Received`,
               * which is called upon a safe transfer, and return the magic value
               * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
               * the transfer is reverted.
               * Requires the msg sender to be the owner, approved, or operator
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
               * @param _data bytes data to send along with a safe transfer check
               */
              function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
                  transferFrom(from, to, tokenId);
                  require(_checkOnERC721Received(from, to, tokenId, _data));
              }
          
              /**
               * @dev Returns whether the specified token exists
               * @param tokenId uint256 ID of the token to query the existence of
               * @return whether the token exists
               */
              function _exists(uint256 tokenId) internal view returns (bool) {
                  address owner = _tokenOwner[tokenId];
                  return owner != address(0);
              }
          
              /**
               * @dev Returns whether the given spender can transfer a given token ID
               * @param spender address of the spender to query
               * @param tokenId uint256 ID of the token to be transferred
               * @return bool whether the msg.sender is approved for the given token ID,
               *    is an operator of the owner, or is the owner of the token
               */
              function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
                  address owner = ownerOf(tokenId);
                  return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
              }
          
              /**
               * @dev Internal function to mint a new token
               * Reverts if the given token ID already exists
               * @param to The address that will own the minted token
               * @param tokenId uint256 ID of the token to be minted
               */
              function _mint(address to, uint256 tokenId) internal {
                  require(to != address(0));
                  require(!_exists(tokenId));
          
                  _tokenOwner[tokenId] = to;
                  _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
          
                  emit Transfer(address(0), to, tokenId);
              }
          
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * Deprecated, use _burn(uint256) instead.
               * @param owner owner of the token to burn
               * @param tokenId uint256 ID of the token being burned
               */
              function _burn(address owner, uint256 tokenId) internal {
                  require(ownerOf(tokenId) == owner);
          
                  _clearApproval(tokenId);
          
                  _ownedTokensCount[owner] = _ownedTokensCount[owner].sub(1);
                  _tokenOwner[tokenId] = address(0);
          
                  emit Transfer(owner, address(0), tokenId);
              }
          
              /**
               * @dev Internal function to burn a specific token
               * Reverts if the token does not exist
               * @param tokenId uint256 ID of the token being burned
               */
              function _burn(uint256 tokenId) internal {
                  _burn(ownerOf(tokenId), tokenId);
              }
          
              /**
               * @dev Internal function to transfer ownership of a given token ID to another address.
               * As opposed to transferFrom, this imposes no restrictions on msg.sender.
               * @param from current owner of the token
               * @param to address to receive the ownership of the given token ID
               * @param tokenId uint256 ID of the token to be transferred
              */
              function _transferFrom(address from, address to, uint256 tokenId) internal {
                  require(ownerOf(tokenId) == from);
                  require(to != address(0));
          
                  _clearApproval(tokenId);
          
                  _ownedTokensCount[from] = _ownedTokensCount[from].sub(1);
                  _ownedTokensCount[to] = _ownedTokensCount[to].add(1);
          
                  _tokenOwner[tokenId] = to;
          
                  emit Transfer(from, to, tokenId);
              }
          
              /**
               * @dev Internal function to invoke `onERC721Received` on a target address
               * The call is not executed if the target address is not a contract
               * @param from address representing the previous owner of the given token ID
               * @param to target address that will receive the tokens
               * @param tokenId uint256 ID of the token to be transferred
               * @param _data bytes optional data to send along with the call
               * @return whether the call correctly returned the expected magic value
               */
              function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
                  internal returns (bool)
              {
                  if (!to.isContract()) {
                      return true;
                  }
          
                  bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data);
                  return (retval == _ERC721_RECEIVED);
              }
          
              /**
               * @dev Private function to clear current approval of a given token ID
               * @param tokenId uint256 ID of the token to be transferred
               */
              function _clearApproval(uint256 tokenId) private {
                  if (_tokenApprovals[tokenId] != address(0)) {
                      _tokenApprovals[tokenId] = address(0);
                  }
              }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: contracts/BaseRegistrar.sol
          
          pragma solidity >=0.4.24;
          
          
          
          
          
          contract BaseRegistrar is ERC721, Ownable {
              uint constant public GRACE_PERIOD = 90 days;
          
              event ControllerAdded(address indexed controller);
              event ControllerRemoved(address indexed controller);
              event NameMigrated(uint256 indexed id, address indexed owner, uint expires);
              event NameRegistered(uint256 indexed id, address indexed owner, uint expires);
              event NameRenewed(uint256 indexed id, uint expires);
          
              // Expiration timestamp for migrated domains.
              uint public transferPeriodEnds;
          
              // The ENS registry
              ENS public ens;
          
              // The namehash of the TLD this registrar owns (eg, .eth)
              bytes32 public baseNode;
          
              // The interim registrar
              HashRegistrar public previousRegistrar;
          
              // A map of addresses that are authorised to register and renew names.
              mapping(address=>bool) public controllers;
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external;
          
              // Revoke controller permission for an address.
              function removeController(address controller) external;
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external;
          
              // Returns the expiration timestamp of the specified label hash.
              function nameExpires(uint256 id) external view returns(uint);
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool);
          
              /**
               * @dev Register a name.
               */
              function register(uint256 id, address owner, uint duration) external returns(uint);
          
              function renew(uint256 id, uint duration) external returns(uint);
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external;
          
              /**
               * @dev Transfers a registration from the initial registrar.
               * This function is called by the initial registrar when a user calls `transferRegistrars`.
               */
              function acceptRegistrarTransfer(bytes32 label, Deed deed, uint) external;
          }
          
          // File: contracts/BaseRegistrarImplementation.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          contract BaseRegistrarImplementation is BaseRegistrar {
              // A map of expiry times
              mapping(uint256=>uint) expiries;
          
              uint constant public MIGRATION_LOCK_PERIOD = 28 days;
          
              bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
              bytes4 constant private ERC721_ID = bytes4(
                  keccak256("balanceOf(uint256)") ^
                  keccak256("ownerOf(uint256)") ^
                  keccak256("approve(address,uint256)") ^
                  keccak256("getApproved(uint256)") ^
                  keccak256("setApprovalForAll(address,bool)") ^
                  keccak256("isApprovedForAll(address,address)") ^
                  keccak256("transferFrom(address,address,uint256)") ^
                  keccak256("safeTransferFrom(address,address,uint256)") ^
                  keccak256("safeTransferFrom(address,address,uint256,bytes)")
              );
              bytes4 constant private RECLAIM_ID = bytes4(keccak256("reclaim(uint256,address)"));
          
              constructor(ENS _ens, HashRegistrar _previousRegistrar, bytes32 _baseNode, uint _transferPeriodEnds) public {
                  // Require that people have time to transfer names over.
                  require(_transferPeriodEnds > now + 2 * MIGRATION_LOCK_PERIOD);
          
                  ens = _ens;
                  baseNode = _baseNode;
                  previousRegistrar = _previousRegistrar;
                  transferPeriodEnds = _transferPeriodEnds;
              }
          
              modifier live {
                  require(ens.owner(baseNode) == address(this));
                  _;
              }
          
              modifier onlyController {
                  require(controllers[msg.sender]);
                  _;
              }
          
              /**
               * @dev Gets the owner of the specified token ID. Names become unowned
               *      when their registration expires.
               * @param tokenId uint256 ID of the token to query the owner of
               * @return address currently marked as the owner of the given token ID
               */
              function ownerOf(uint256 tokenId) public view returns (address) {
                  require(expiries[tokenId] > now);
                  return super.ownerOf(tokenId);
              }
          
              // Authorises a controller, who can register and renew domains.
              function addController(address controller) external onlyOwner {
                  controllers[controller] = true;
                  emit ControllerAdded(controller);
              }
          
              // Revoke controller permission for an address.
              function removeController(address controller) external onlyOwner {
                  controllers[controller] = false;
                  emit ControllerRemoved(controller);
              }
          
              // Set the resolver for the TLD this registrar manages.
              function setResolver(address resolver) external onlyOwner {
                  ens.setResolver(baseNode, resolver);
              }
          
              // Returns the expiration timestamp of the specified id.
              function nameExpires(uint256 id) external view returns(uint) {
                  return expiries[id];
              }
          
              // Returns true iff the specified name is available for registration.
              function available(uint256 id) public view returns(bool) {
                  // Not available if it's registered here or in its grace period.
                  if(expiries[id] + GRACE_PERIOD >= now) {
                      return false;
                  }
                  // Available if we're past the transfer period, or the name isn't
                  // registered in the legacy registrar.
                  return now > transferPeriodEnds || previousRegistrar.state(bytes32(id)) == Registrar.Mode.Open;
              }
          
              /**
               * @dev Register a name.
               */
              function register(uint256 id, address owner, uint duration) external live onlyController returns(uint) {
                  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);
                  ens.setSubnodeOwner(baseNode, bytes32(id), owner);
          
                  emit NameRegistered(id, owner, now + duration);
          
                  return now + duration;
              }
          
              function renew(uint256 id, uint duration) external live onlyController returns(uint) {
                  require(expiries[id] + GRACE_PERIOD >= now); // Name must be registered here or in grace period
                  require(expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD); // Prevent future overflow
          
                  expiries[id] += duration;
                  emit NameRenewed(id, expiries[id]);
                  return expiries[id];
              }
          
              /**
               * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
               */
              function reclaim(uint256 id, address owner) external live {
                  require(_isApprovedOrOwner(msg.sender, id));
                  ens.setSubnodeOwner(baseNode, bytes32(id), owner);
              }
          
              /**
               * @dev Transfers a registration from the initial registrar.
               * This function is called by the initial registrar when a user calls `transferRegistrars`.
               */
              function acceptRegistrarTransfer(bytes32 label, Deed deed, uint) external live {
                  uint256 id = uint256(label);
          
                  require(msg.sender == address(previousRegistrar));
                  require(expiries[id] == 0);
                  require(transferPeriodEnds > now);
          
                  uint registrationDate;
                  (,,registrationDate,,) = previousRegistrar.entries(label);
                  require(registrationDate < now - MIGRATION_LOCK_PERIOD);
          
                  address owner = deed.owner();
          
                  // Destroy the deed and transfer the funds back to the registrant.
                  deed.closeDeed(1000);
          
                  // Register the name
                  expiries[id] = transferPeriodEnds;
                  _mint(owner, id);
          
                  ens.setSubnodeOwner(baseNode, label, owner);
          
                  emit NameMigrated(id, owner, transferPeriodEnds);
                  emit NameRegistered(id, owner, transferPeriodEnds);
              }
          
              function supportsInterface(bytes4 interfaceID) external view returns (bool) {
                  return interfaceID == INTERFACE_META_ID ||
                         interfaceID == ERC721_ID ||
                         interfaceID == RECLAIM_ID;
              }
          }

          File 3 of 6: ENS
          ;;; --------------------------------------------------------------------------- 
          ;;; @title The Ethereum Name Service registry. 
          ;;; @author Daniel Ellison <[email protected]> 
           
          (seq 
           
            ;; -------------------------------------------------------------------------- 
            ;; Constant definitions. 
           
            ;; Memory layout. 
            (def 'node-bytes  0x00) 
            (def 'label-bytes 0x20) 
            (def 'call-result 0x40) 
           
            ;; Struct: Record 
            (def 'resolver 0x00) ; address 
            (def 'owner    0x20) ; address 
            (def 'ttl      0x40) ; uint64 
           
            ;; Precomputed function IDs. 
            (def 'get-node-owner    0x02571be3) ; owner(bytes32) 
            (def 'get-node-resolver 0x0178b8bf) ; resolver(bytes32) 
            (def 'get-node-ttl      0x16a25cbd) ; ttl(bytes32) 
            (def 'set-node-owner    0x5b0fc9c3) ; setOwner(bytes32,address) 
            (def 'set-subnode-owner 0x06ab5923) ; setSubnodeOwner(bytes32,bytes32,address) 
            (def 'set-node-resolver 0x1896f70a) ; setResolver(bytes32,address) 
            (def 'set-node-ttl      0x14ab9038) ; setTTL(bytes32,uint64) 
           
            ;; Jumping here causes an EVM error. 
            (def 'invalid-location 0x02) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Shifts the leftmost 4 bytes of a 32-byte number right by 28 bytes. 
            ;; @param input A 32-byte number. 
           
            (def 'shift-right (input) 
              (div input (exp 2 224))) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Determines whether the supplied function ID matches a known 
            ;;         function hash and executes <code-body> if so. 
            ;; @dev The function ID is in the leftmost four bytes of the call data. 
            ;; @param function-hash The four-byte hash of a known function signature. 
            ;; @param code-body The code to run in the case of a match. 
           
            (def 'function (function-hash code-body) 
              (when (= (shift-right (calldataload 0x00)) function-hash) 
                code-body)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Calculates record location for the node and label passed in. 
            ;; @param node The parent node. 
            ;; @param label The hash of the subnode label. 
           
            (def 'get-record (node label) 
              (seq 
                (mstore node-bytes node) 
                (mstore label-bytes label) 
                (sha3 node-bytes 64))) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Retrieves owner from node record. 
            ;; @param node Get owner of this node. 
           
            (def 'get-owner (node) 
              (sload (+ node owner))) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Stores new owner in node record. 
            ;; @param node Set owner of this node. 
            ;; @param new-owner New owner of this node. 
           
            (def 'set-owner (node new-owner) 
              (sstore (+ node owner) new-owner)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Stores new subnode owner in node record. 
            ;; @param node Set owner of this node. 
            ;; @param label The hash of the label specifying the subnode. 
            ;; @param new-owner New owner of the subnode. 
           
            (def 'set-subowner (node label new-owner) 
              (sstore (+ (get-record node label) owner) new-owner)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Retrieves resolver from node record. 
            ;; @param node Get resolver of this node. 
           
            (def 'get-resolver (node) 
              (sload node)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Stores new resolver in node record. 
            ;; @param node Set resolver of this node. 
            ;; @param new-resolver New resolver for this node. 
           
            (def 'set-resolver (node new-resolver) 
              (sstore node new-resolver)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Retrieves TTL From node record. 
            ;; @param node Get TTL of this node. 
           
            (def 'get-ttl (node) 
              (sload (+ node ttl))) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Stores new TTL in node record. 
            ;; @param node Set TTL of this node. 
            ;; @param new-resolver New TTL for this node. 
           
            (def 'set-ttl (node new-ttl) 
              (sstore (+ node ttl) new-ttl)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; @notice Checks that the caller is the node owner. 
            ;; @param node Check owner of this node. 
           
            (def 'only-node-owner (node) 
              (when (!= (caller) (get-owner node)) 
                (jump invalid-location))) 
           
            ;; -------------------------------------------------------------------------- 
            ;; INIT 
           
            ;; Set the owner of the root node (0x00) to the deploying account. 
            (set-owner 0x00 (caller)) 
           
            ;; -------------------------------------------------------------------------- 
            ;; CODE 
           
            (returnlll 
              (seq 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Returns the address of the resolver for the specified node. 
                ;; @dev Signature: resolver(bytes32) 
                ;; @param node Return this node's resolver. 
                ;; @return The associated resolver. 
           
                (def 'node (calldataload 0x04)) 
           
                (function get-node-resolver 
                  (seq 
           
                    ;; Get the node's resolver and save it. 
                    (mstore call-result (get-resolver node)) 
           
                    ;; Return result. 
                    (return call-result 32))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Returns the address that owns the specified node. 
                ;; @dev Signature: owner(bytes32) 
                ;; @param node Return this node's owner. 
                ;; @return The associated address. 
           
                (def 'node (calldataload 0x04)) 
           
                (function get-node-owner 
                  (seq 
           
                    ;; Get the node's owner and save it. 
                    (mstore call-result (get-owner node)) 
           
                    ;; Return result. 
                    (return call-result 32))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Returns the TTL of a node and any records associated with it. 
                ;; @dev Signature: ttl(bytes32) 
                ;; @param node Return this node's TTL. 
                ;; @return The node's TTL. 
           
                (def 'node (calldataload 0x04)) 
           
                (function get-node-ttl 
                  (seq 
           
                    ;; Get the node's TTL and save it. 
                    (mstore call-result (get-ttl node)) 
           
                    ;; Return result. 
                    (return call-result 32))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Transfers ownership of a node to a new address. May only be 
                ;;         called by the current owner of the node. 
                ;; @dev Signature: setOwner(bytes32,address) 
                ;; @param node The node to transfer ownership of. 
                ;; @param new-owner The address of the new owner. 
           
                (def 'node (calldataload 0x04)) 
                (def 'new-owner (calldataload 0x24)) 
           
                (function set-node-owner 
                  (seq (only-node-owner node) 
           
                    ;; Transfer ownership by storing passed-in address. 
                    (set-owner node new-owner) 
           
                    ;; Emit an event about the transfer. 
                    ;; Transfer(bytes32 indexed node, address owner); 
                    (mstore call-result new-owner) 
                    (log2 call-result 32 
                        (sha3 0x00 (lit 0x00 "Transfer(bytes32,address)")) node) 
           
                    ;; Nothing to return. 
                    (stop))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Transfers ownership of a subnode to a new address. May only be 
                ;;         called by the owner of the parent node. 
                ;; @dev Signature: setSubnodeOwner(bytes32,bytes32,address) 
                ;; @param node The parent node. 
                ;; @param label The hash of the label specifying the subnode. 
                ;; @param new-owner The address of the new owner. 
           
                (def 'node (calldataload 0x04)) 
                (def 'label (calldataload 0x24)) 
                (def 'new-owner (calldataload 0x44)) 
           
                (function set-subnode-owner 
                  (seq (only-node-owner node) 
           
                    ;; Transfer ownership by storing passed-in address. 
                    (set-subowner node label new-owner) 
           
                    ;; Emit an event about the transfer. 
                    ;; NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); 
                    (mstore call-result new-owner) 
                    (log3 call-result 32 
                        (sha3 0x00 (lit 0x00 "NewOwner(bytes32,bytes32,address)")) 
                        node label) 
           
                    ;; Nothing to return. 
                    (stop))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Sets the resolver address for the specified node. 
                ;; @dev Signature: setResolver(bytes32,address) 
                ;; @param node The node to update. 
                ;; @param new-resolver The address of the resolver. 
           
                (def 'node (calldataload 0x04)) 
                (def 'new-resolver (calldataload 0x24)) 
           
                (function set-node-resolver 
                  (seq (only-node-owner node) 
           
                    ;; Transfer ownership by storing passed-in address. 
                    (set-resolver node new-resolver) 
           
                    ;; Emit an event about the change of resolver. 
                    ;; NewResolver(bytes32 indexed node, address resolver); 
                    (mstore call-result new-resolver) 
                    (log2 call-result 32 
                        (sha3 0x00 (lit 0x00 "NewResolver(bytes32,address)")) node) 
           
                    ;; Nothing to return. 
                    (stop))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Sets the TTL for the specified node. 
                ;; @dev Signature: setTTL(bytes32,uint64) 
                ;; @param node The node to update. 
                ;; @param ttl The TTL in seconds. 
           
                (def 'node (calldataload 0x04)) 
                (def 'new-ttl (calldataload 0x24)) 
           
                (function set-node-ttl 
                  (seq (only-node-owner node) 
           
                    ;; Set new TTL by storing passed-in time. 
                    (set-ttl node new-ttl) 
           
                    ;; Emit an event about the change of TTL. 
                    ;; NewTTL(bytes32 indexed node, uint64 ttl); 
                    (mstore call-result new-ttl) 
                    (log2 call-result 32 
                        (sha3 0x00 (lit 0x00 "NewTTL(bytes32,uint64)")) node) 
           
                    ;; Nothing to return. 
                    (stop))) 
           
                ;; ---------------------------------------------------------------------- 
                ;; @notice Fallback: No functions matched the function ID provided. 
           
                (jump invalid-location))) 
           
          )

          File 4 of 6: Registrar
          pragma solidity ^0.4.0;
          
          
          /*
          
          Temporary Hash Registrar
          ========================
          
          This is a simplified version of a hash registrar. It is purporsefully limited:
          names cannot be six letters or shorter, new auctions will stop after 4 years.
          
          The plan is to test the basic features and then move to a new contract in at most
          2 years, when some sort of renewal mechanism will be enabled.
          */
          
          contract AbstractENS {
              function owner(bytes32 node) constant returns(address);
              function resolver(bytes32 node) constant returns(address);
              function ttl(bytes32 node) constant returns(uint64);
              function setOwner(bytes32 node, address owner);
              function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
              function setResolver(bytes32 node, address resolver);
              function setTTL(bytes32 node, uint64 ttl);
          
              // Logged when the owner of a node assigns a new owner to a subnode.
              event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
          
              // Logged when the owner of a node transfers ownership to a new account.
              event Transfer(bytes32 indexed node, address owner);
          
              // Logged when the resolver for a node changes.
              event NewResolver(bytes32 indexed node, address resolver);
          
              // Logged when the TTL of a node changes
              event NewTTL(bytes32 indexed node, uint64 ttl);
          }
          
          /**
           * @title Deed to hold ether in exchange for ownership of a node
           * @dev The deed can be controlled only by the registrar and can only send ether back to the owner.
           */
          contract Deed {
              address public registrar;
              address constant burn = 0xdead;
              uint public creationDate;
              address public owner;
              address public previousOwner;
              uint public value;
              event OwnerChanged(address newOwner);
              event DeedClosed();
              bool active;
          
          
              modifier onlyRegistrar {
                  if (msg.sender != registrar) throw;
                  _;
              }
          
              modifier onlyActive {
                  if (!active) throw;
                  _;
              }
          
              function Deed(address _owner) payable {
                  owner = _owner;
                  registrar = msg.sender;
                  creationDate = now;
                  active = true;
                  value = msg.value;
              }
          
              function setOwner(address newOwner) onlyRegistrar {
                  if (newOwner == 0) throw;
                  previousOwner = owner;  // This allows contracts to check who sent them the ownership
                  owner = newOwner;
                  OwnerChanged(newOwner);
              }
          
              function setRegistrar(address newRegistrar) onlyRegistrar {
                  registrar = newRegistrar;
              }
          
              function setBalance(uint newValue, bool throwOnFailure) onlyRegistrar onlyActive {
                  // Check if it has enough balance to set the value
                  if (value < newValue) throw;
                  value = newValue;
                  // Send the difference to the owner
                  if (!owner.send(this.balance - newValue) && throwOnFailure) throw;
              }
          
              /**
               * @dev Close a deed and refund a specified fraction of the bid value
               * @param refundRatio The amount*1/1000 to refund
               */
              function closeDeed(uint refundRatio) onlyRegistrar onlyActive {
                  active = false;
                  if (! burn.send(((1000 - refundRatio) * this.balance)/1000)) throw;
                  DeedClosed();
                  destroyDeed();
              }
          
              /**
               * @dev Close a deed and refund a specified fraction of the bid value
               */
              function destroyDeed() {
                  if (active) throw;
                  
                  // Instead of selfdestruct(owner), invoke owner fallback function to allow
                  // owner to log an event if desired; but owner should also be aware that
                  // its fallback function can also be invoked by setBalance
                  if(owner.send(this.balance)) {
                      selfdestruct(burn);
                  }
              }
          }
          
          /**
           * @title Registrar
           * @dev The registrar handles the auction process for each subnode of the node it owns.
           */
          contract Registrar {
              AbstractENS public ens;
              bytes32 public rootNode;
          
              mapping (bytes32 => entry) _entries;
              mapping (address => mapping(bytes32 => Deed)) public sealedBids;
              
              enum Mode { Open, Auction, Owned, Forbidden, Reveal, NotYetAvailable }
          
              uint32 constant totalAuctionLength = 5 days;
              uint32 constant revealPeriod = 48 hours;
              uint32 public constant launchLength = 8 weeks;
          
              uint constant minPrice = 0.01 ether;
              uint public registryStarted;
          
              event AuctionStarted(bytes32 indexed hash, uint registrationDate);
              event NewBid(bytes32 indexed hash, address indexed bidder, uint deposit);
              event BidRevealed(bytes32 indexed hash, address indexed owner, uint value, uint8 status);
              event HashRegistered(bytes32 indexed hash, address indexed owner, uint value, uint registrationDate);
              event HashReleased(bytes32 indexed hash, uint value);
              event HashInvalidated(bytes32 indexed hash, string indexed name, uint value, uint registrationDate);
          
              struct entry {
                  Deed deed;
                  uint registrationDate;
                  uint value;
                  uint highestBid;
              }
          
              // State transitions for names:
              //   Open -> Auction (startAuction)
              //   Auction -> Reveal
              //   Reveal -> Owned
              //   Reveal -> Open (if nobody bid)
              //   Owned -> Open (releaseDeed or invalidateName)
              function state(bytes32 _hash) constant returns (Mode) {
                  var entry = _entries[_hash];
                  
                  if(!isAllowed(_hash, now)) {
                      return Mode.NotYetAvailable;
                  } else if(now < entry.registrationDate) {
                      if (now < entry.registrationDate - revealPeriod) {
                          return Mode.Auction;
                      } else {
                          return Mode.Reveal;
                      }
                  } else {
                      if(entry.highestBid == 0) {
                          return Mode.Open;
                      } else {
                          return Mode.Owned;
                      }
                  }
              }
          
              modifier inState(bytes32 _hash, Mode _state) {
                  if(state(_hash) != _state) throw;
                  _;
              }
          
              modifier onlyOwner(bytes32 _hash) {
                  if (state(_hash) != Mode.Owned || msg.sender != _entries[_hash].deed.owner()) throw;
                  _;
              }
          
              modifier registryOpen() {
                  if(now < registryStarted  || now > registryStarted + 4 years || ens.owner(rootNode) != address(this)) throw;
                  _;
              }
          
              function entries(bytes32 _hash) constant returns (Mode, address, uint, uint, uint) {
                  entry h = _entries[_hash];
                  return (state(_hash), h.deed, h.registrationDate, h.value, h.highestBid);
              }
          
              /**
               * @dev Constructs a new Registrar, with the provided address as the owner of the root node.
               * @param _ens The address of the ENS
               * @param _rootNode The hash of the rootnode.
               */
              function Registrar(AbstractENS _ens, bytes32 _rootNode, uint _startDate) {
                  ens = _ens;
                  rootNode = _rootNode;
                  registryStarted = _startDate > 0 ? _startDate : now;
              }
          
              /**
               * @dev Returns the maximum of two unsigned integers
               * @param a A number to compare
               * @param b A number to compare
               * @return The maximum of two unsigned integers
               */
              function max(uint a, uint b) internal constant returns (uint max) {
                  if (a > b)
                      return a;
                  else
                      return b;
              }
          
              /**
               * @dev Returns the minimum of two unsigned integers
               * @param a A number to compare
               * @param b A number to compare
               * @return The minimum of two unsigned integers
               */
              function min(uint a, uint b) internal constant returns (uint min) {
                  if (a < b)
                      return a;
                  else
                      return b;
              }
          
              /**
               * @dev Returns the length of a given string
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string s) internal constant returns (uint) {
                  // Starting here means the LSB will be the byte we care about
                  uint ptr;
                  uint end;
                  assembly {
                      ptr := add(s, 1)
                      end := add(mload(s), ptr)
                  }
                  for (uint len = 0; ptr < end; len++) {
                      uint8 b;
                      assembly { b := and(mload(ptr), 0xFF) }
                      if (b < 0x80) {
                          ptr += 1;
                      } else if(b < 0xE0) {
                          ptr += 2;
                      } else if(b < 0xF0) {
                          ptr += 3;
                      } else if(b < 0xF8) {
                          ptr += 4;
                      } else if(b < 0xFC) {
                          ptr += 5;
                      } else {
                          ptr += 6;
                      }
                  }
                  return len;
              }
              
              /** 
               * @dev Determines if a name is available for registration yet
               * 
               * Each name will be assigned a random date in which its auction 
               * can be started, from 0 to 13 weeks
               * 
               * @param _hash The hash to start an auction on
               * @param _timestamp The timestamp to query about
               */
               
              function isAllowed(bytes32 _hash, uint _timestamp) constant returns (bool allowed){
                  return _timestamp > getAllowedTime(_hash);
              }
          
              /** 
               * @dev Returns available date for hash
               * 
               * @param _hash The hash to start an auction on
               */
              function getAllowedTime(bytes32 _hash) constant returns (uint timestamp) {
                  return registryStarted + (launchLength*(uint(_hash)>>128)>>128);
                  // right shift operator: a >> b == a / 2**b
              }
              /**
               * @dev Assign the owner in ENS, if we're still the registrar
               * @param _hash hash to change owner
               * @param _newOwner new owner to transfer to
               */
              function trySetSubnodeOwner(bytes32 _hash, address _newOwner) internal {
                  if(ens.owner(rootNode) == address(this))
                      ens.setSubnodeOwner(rootNode, _hash, _newOwner);        
              }
          
              /**
               * @dev Start an auction for an available hash
               *
               * Anyone can start an auction by sending an array of hashes that they want to bid for.
               * Arrays are sent so that someone can open up an auction for X dummy hashes when they
               * are only really interested in bidding for one. This will increase the cost for an
               * attacker to simply bid blindly on all new auctions. Dummy auctions that are
               * open but not bid on are closed after a week.
               *
               * @param _hash The hash to start an auction on
               */
              function startAuction(bytes32 _hash) registryOpen() {
                  var mode = state(_hash);
                  if(mode == Mode.Auction) return;
                  if(mode != Mode.Open) throw;
          
                  entry newAuction = _entries[_hash];
                  newAuction.registrationDate = now + totalAuctionLength;
                  newAuction.value = 0;
                  newAuction.highestBid = 0;
                  AuctionStarted(_hash, newAuction.registrationDate);
              }
          
              /**
               * @dev Start multiple auctions for better anonymity
               * @param _hashes An array of hashes, at least one of which you presumably want to bid on
               */
              function startAuctions(bytes32[] _hashes)  {
                  for (uint i = 0; i < _hashes.length; i ++ ) {
                      startAuction(_hashes[i]);
                  }
              }
          
              /**
               * @dev Hash the values required for a secret bid
               * @param hash The node corresponding to the desired namehash
               * @param value The bid amount
               * @param salt A random value to ensure secrecy of the bid
               * @return The hash of the bid values
               */
              function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) constant returns (bytes32 sealedBid) {
                  return sha3(hash, owner, value, salt);
              }
          
              /**
               * @dev Submit a new sealed bid on a desired hash in a blind auction
               *
               * Bids are sent by sending a message to the main contract with a hash and an amount. The hash
               * contains information about the bid, including the bidded hash, the bid amount, and a random
               * salt. Bids are not tied to any one auction until they are revealed. The value of the bid
               * itself can be masqueraded by sending more than the value of your actual bid. This is
               * followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable.
               * Since this is an auction, it is expected that most public hashes, like known domains and common dictionary
               * words, will have multiple bidders pushing the price up.
               *
               * @param sealedBid A sealedBid, created by the shaBid function
               */
              function newBid(bytes32 sealedBid) payable {
                  if (address(sealedBids[msg.sender][sealedBid]) > 0 ) throw;
                  if (msg.value < minPrice) throw;
                  // creates a new hash contract with the owner
                  Deed newBid = (new Deed).value(msg.value)(msg.sender);
                  sealedBids[msg.sender][sealedBid] = newBid;
                  NewBid(sealedBid, msg.sender, msg.value);
              }
          
              /**
               * @dev Start a set of auctions and bid on one of them
               *
               * This method functions identically to calling `startAuctions` followed by `newBid`,
               * but all in one transaction.
               * @param hashes A list of hashes to start auctions on.
               * @param sealedBid A sealed bid for one of the auctions.
               */
              function startAuctionsAndBid(bytes32[] hashes, bytes32 sealedBid) payable {
                  startAuctions(hashes);
                  newBid(sealedBid);
              }
          
              /**
               * @dev Submit the properties of a bid to reveal them
               * @param _hash The node in the sealedBid
               * @param _value The bid amount in the sealedBid
               * @param _salt The sale in the sealedBid
               */
              function unsealBid(bytes32 _hash, uint _value, bytes32 _salt) {
                  bytes32 seal = shaBid(_hash, msg.sender, _value, _salt);
                  Deed bid = sealedBids[msg.sender][seal];
                  if (address(bid) == 0 ) throw;
                  sealedBids[msg.sender][seal] = Deed(0);
                  entry h = _entries[_hash];
                  uint value = min(_value, bid.value());
                  bid.setBalance(value, true);
          
                  var auctionState = state(_hash);
                  if(auctionState == Mode.Owned) {
                      // Too late! Bidder loses their bid. Get's 0.5% back.
                      bid.closeDeed(5);
                      BidRevealed(_hash, msg.sender, value, 1);
                  } else if(auctionState != Mode.Reveal) {
                      // Invalid phase
                      throw;
                  } else if (value < minPrice || bid.creationDate() > h.registrationDate - revealPeriod) {
                      // Bid too low or too late, refund 99.5%
                      bid.closeDeed(995);
                      BidRevealed(_hash, msg.sender, value, 0);
                  } else if (value > h.highestBid) {
                      // new winner
                      // cancel the other bid, refund 99.5%
                      if(address(h.deed) != 0) {
                          Deed previousWinner = h.deed;
                          previousWinner.closeDeed(995);
                      }
          
                      // set new winner
                      // per the rules of a vickery auction, the value becomes the previous highestBid
                      h.value = h.highestBid;  // will be zero if there's only 1 bidder
                      h.highestBid = value;
                      h.deed = bid;
                      BidRevealed(_hash, msg.sender, value, 2);
                  } else if (value > h.value) {
                      // not winner, but affects second place
                      h.value = value;
                      bid.closeDeed(995);
                      BidRevealed(_hash, msg.sender, value, 3);
                  } else {
                      // bid doesn't affect auction
                      bid.closeDeed(995);
                      BidRevealed(_hash, msg.sender, value, 4);
                  }
              }
          
              /**
               * @dev Cancel a bid
               * @param seal The value returned by the shaBid function
               */
              function cancelBid(address bidder, bytes32 seal) {
                  Deed bid = sealedBids[bidder][seal];
                  
                  // If a sole bidder does not `unsealBid` in time, they have a few more days
                  // where they can call `startAuction` (again) and then `unsealBid` during
                  // the revealPeriod to get back their bid value.
                  // For simplicity, they should call `startAuction` within
                  // 9 days (2 weeks - totalAuctionLength), otherwise their bid will be
                  // cancellable by anyone.
                  if (address(bid) == 0
                      || now < bid.creationDate() + totalAuctionLength + 2 weeks) throw;
          
                  // Send the canceller 0.5% of the bid, and burn the rest.
                  bid.setOwner(msg.sender);
                  bid.closeDeed(5);
                  sealedBids[bidder][seal] = Deed(0);
                  BidRevealed(seal, bidder, 0, 5);
              }
          
              /**
               * @dev Finalize an auction after the registration date has passed
               * @param _hash The hash of the name the auction is for
               */
              function finalizeAuction(bytes32 _hash) onlyOwner(_hash) {
                  entry h = _entries[_hash];
                  
                  // handles the case when there's only a single bidder (h.value is zero)
                  h.value =  max(h.value, minPrice);
                  h.deed.setBalance(h.value, true);
          
                  trySetSubnodeOwner(_hash, h.deed.owner());
                  HashRegistered(_hash, h.deed.owner(), h.value, h.registrationDate);
              }
          
              /**
               * @dev The owner of a domain may transfer it to someone else at any time.
               * @param _hash The node to transfer
               * @param newOwner The address to transfer ownership to
               */
              function transfer(bytes32 _hash, address newOwner) onlyOwner(_hash) {
                  if (newOwner == 0) throw;
          
                  entry h = _entries[_hash];
                  h.deed.setOwner(newOwner);
                  trySetSubnodeOwner(_hash, newOwner);
              }
          
              /**
               * @dev After some time, or if we're no longer the registrar, the owner can release
               *      the name and get their ether back.
               * @param _hash The node to release
               */
              function releaseDeed(bytes32 _hash) onlyOwner(_hash) {
                  entry h = _entries[_hash];
                  Deed deedContract = h.deed;
                  if(now < h.registrationDate + 1 years && ens.owner(rootNode) == address(this)) throw;
          
                  h.value = 0;
                  h.highestBid = 0;
                  h.deed = Deed(0);
          
                  _tryEraseSingleNode(_hash);
                  deedContract.closeDeed(1000);
                  HashReleased(_hash, h.value);        
              }
          
              /**
               * @dev Submit a name 6 characters long or less. If it has been registered,
               * the submitter will earn 50% of the deed value. We are purposefully
               * handicapping the simplified registrar as a way to force it into being restructured
               * in a few years.
               * @param unhashedName An invalid name to search for in the registry.
               *
               */
              function invalidateName(string unhashedName) inState(sha3(unhashedName), Mode.Owned) {
                  if (strlen(unhashedName) > 6 ) throw;
                  bytes32 hash = sha3(unhashedName);
          
                  entry h = _entries[hash];
          
                  _tryEraseSingleNode(hash);
          
                  if(address(h.deed) != 0) {
                      // Reward the discoverer with 50% of the deed
                      // The previous owner gets 50%
                      h.value = max(h.value, minPrice);
                      h.deed.setBalance(h.value/2, false);
                      h.deed.setOwner(msg.sender);
                      h.deed.closeDeed(1000);
                  }
          
                  HashInvalidated(hash, unhashedName, h.value, h.registrationDate);
          
                  h.value = 0;
                  h.highestBid = 0;
                  h.deed = Deed(0);
              }
          
              /**
               * @dev Allows anyone to delete the owner and resolver records for a (subdomain of) a
               *      name that is not currently owned in the registrar. If passing, eg, 'foo.bar.eth',
               *      the owner and resolver fields on 'foo.bar.eth' and 'bar.eth' will all be cleared.
               * @param labels A series of label hashes identifying the name to zero out, rooted at the
               *        registrar's root. Must contain at least one element. For instance, to zero 
               *        'foo.bar.eth' on a registrar that owns '.eth', pass an array containing
               *        [sha3('foo'), sha3('bar')].
               */
              function eraseNode(bytes32[] labels) {
                  if(labels.length == 0) throw;
                  if(state(labels[labels.length - 1]) == Mode.Owned) throw;
          
                  _eraseNodeHierarchy(labels.length - 1, labels, rootNode);
              }
          
              function _tryEraseSingleNode(bytes32 label) internal {
                  if(ens.owner(rootNode) == address(this)) {
                      ens.setSubnodeOwner(rootNode, label, address(this));
                      var node = sha3(rootNode, label);
                      ens.setResolver(node, 0);
                      ens.setOwner(node, 0);
                  }
              }
          
              function _eraseNodeHierarchy(uint idx, bytes32[] labels, bytes32 node) internal {
                  // Take ownership of the node
                  ens.setSubnodeOwner(node, labels[idx], address(this));
                  node = sha3(node, labels[idx]);
                  
                  // Recurse if there's more labels
                  if(idx > 0)
                      _eraseNodeHierarchy(idx - 1, labels, node);
          
                  // Erase the resolver and owner records
                  ens.setResolver(node, 0);
                  ens.setOwner(node, 0);
              }
          
              /**
               * @dev Transfers the deed to the current registrar, if different from this one.
               * Used during the upgrade process to a permanent registrar.
               * @param _hash The name hash to transfer.
               */
              function transferRegistrars(bytes32 _hash) onlyOwner(_hash) {
                  var registrar = ens.owner(rootNode);
                  if(registrar == address(this))
                      throw;
          
                  // Migrate the deed
                  entry h = _entries[_hash];
                  h.deed.setRegistrar(registrar);
          
                  // Call the new registrar to accept the transfer
                  Registrar(registrar).acceptRegistrarTransfer(_hash, h.deed, h.registrationDate);
          
                  // Zero out the entry
                  h.deed = Deed(0);
                  h.registrationDate = 0;
                  h.value = 0;
                  h.highestBid = 0;
              }
          
              /**
               * @dev Accepts a transfer from a previous registrar; stubbed out here since there
               *      is no previous registrar implementing this interface.
               * @param hash The sha3 hash of the label to transfer.
               * @param deed The Deed object for the name being transferred in.
               * @param registrationDate The date at which the name was originally registered.
               */
              function acceptRegistrarTransfer(bytes32 hash, Deed deed, uint registrationDate) {}
          
          }

          File 5 of 6: StablePriceOracle
          // File: contracts/PriceOracle.sol
          
          pragma solidity >=0.4.24;
          
          interface PriceOracle {
              /**
               * @dev Returns the price to register or renew a name.
               * @param name The name being registered or renewed.
               * @param expires When the name presently expires (0 if this is a new registration).
               * @param duration How long the name is being registered or extended for, in seconds.
               * @return The price of this renewal or registration, in wei.
               */
              function price(string calldata name, uint expires, uint duration) external view returns(uint);
          }
          
          // File: contracts/SafeMath.sol
          
          pragma solidity >=0.4.24;
          
          /**
           * @title SafeMath
           * @dev Unsigned math operations with safety checks that revert on error
           */
          library SafeMath {
              /**
              * @dev Multiplies two unsigned integers, reverts on overflow.
              */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
          
                  uint256 c = a * b;
                  require(c / a == b);
          
                  return c;
              }
          
              /**
              * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
              */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Solidity only automatically asserts when dividing by 0
                  require(b > 0);
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
              * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
          
                  return c;
              }
          
              /**
              * @dev Adds two unsigned integers, reverts on overflow.
              */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
          
                  return c;
              }
          
              /**
              * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
              * reverts when dividing by zero.
              */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0);
                  return a % b;
              }
          }
          
          // File: contracts/StringUtils.sol
          
          pragma solidity >=0.4.24;
          
          library StringUtils {
              /**
               * @dev Returns the length of a given string
               *
               * @param s The string to measure the length of
               * @return The length of the input string
               */
              function strlen(string memory s) internal pure returns (uint) {
                  uint len;
                  uint i = 0;
                  uint bytelength = bytes(s).length;
                  for(len = 0; i < bytelength; len++) {
                      byte b = bytes(s)[i];
                      if(b < 0x80) {
                          i += 1;
                      } else if (b < 0xE0) {
                          i += 2;
                      } else if (b < 0xF0) {
                          i += 3;
                      } else if (b < 0xF8) {
                          i += 4;
                      } else if (b < 0xFC) {
                          i += 5;
                      } else {
                          i += 6;
                      }
                  }
                  return len;
              }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          pragma solidity ^0.5.0;
          
          /**
           * @title Ownable
           * @dev The Ownable contract has an owner address, and provides basic authorization control
           * functions, this simplifies the implementation of "user permissions".
           */
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          // File: contracts/StablePriceOracle.sol
          
          pragma solidity ^0.5.0;
          
          
          
          
          
          interface DSValue {
              function read() external view returns (bytes32);
          }
          
          // StablePriceOracle sets a price in USD, based on an oracle.
          contract StablePriceOracle is Ownable, PriceOracle {
              using SafeMath for *;
              using StringUtils for *;
          
              // Oracle address
              DSValue usdOracle;
          
              // Rent in attodollars (1e-18) per second
              uint[] public rentPrices;
          
              event OracleChanged(address oracle);
              event RentPriceChanged(uint[] prices);
          
              constructor(DSValue _usdOracle, uint[] memory _rentPrices) public {
                  setOracle(_usdOracle);
                  setPrices(_rentPrices);
              }
          
              /**
               * @dev Sets the price oracle address
               * @param _usdOracle The address of the price oracle to use.
               */
              function setOracle(DSValue _usdOracle) public onlyOwner {
                  usdOracle = _usdOracle;
                  emit OracleChanged(address(_usdOracle));
              }
          
              /**
               * @dev Sets rent prices.
               * @param _rentPrices The price array. Each element corresponds to a specific
               *                    name length; names longer than the length of the array
               *                    default to the price of the last element.
               */
              function setPrices(uint[] memory _rentPrices) public onlyOwner {
                  rentPrices = _rentPrices;
                  emit RentPriceChanged(_rentPrices);
              }
          
              /**
               * @dev Returns the price to register or renew a name.
               * @param name The name being registered or renewed.
               * @param duration How long the name is being registered or extended for, in seconds.
               * @return The price of this renewal or registration, in wei.
               */
              function price(string calldata name, uint /*expires*/, uint duration) view external returns(uint) {
                  uint len = name.strlen();
                  if(len > rentPrices.length) {
                      len = rentPrices.length;
                  }
                  require(len > 0);
                  uint priceUSD = rentPrices[len - 1].mul(duration);
          
                  // Price of one ether in attodollars
                  uint ethPrice = uint(usdOracle.read());
          
                  // priceUSD and ethPrice are both fixed-point values with 18dp, so we
                  // multiply the numerator by 1e18 before dividing.
                  return priceUSD.mul(1e18).div(ethPrice);
              }
          }

          File 6 of 6: Medianizer
          /// return median value of feeds
          
          // Copyright (C) 2017  DappHub, LLC
          
          // Licensed under the Apache License, Version 2.0 (the "License").
          // You may not use this file except in compliance with the License.
          
          // Unless required by applicable law or agreed to in writing, software
          // distributed under the License is distributed on an "AS IS" BASIS,
          // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied).
          
          pragma solidity ^0.4.8;
          
          contract DSAuthority {
              function canCall(
                  address src, address dst, bytes4 sig
              ) constant returns (bool);
          }
          
          contract DSAuthEvents {
              event LogSetAuthority (address indexed authority);
              event LogSetOwner     (address indexed owner);
          }
          
          contract DSAuth is DSAuthEvents {
              DSAuthority  public  authority;
              address      public  owner;
          
              function DSAuth() {
                  owner = msg.sender;
                  LogSetOwner(msg.sender);
              }
          
              function setOwner(address owner_)
                  auth
              {
                  owner = owner_;
                  LogSetOwner(owner);
              }
          
              function setAuthority(DSAuthority authority_)
                  auth
              {
                  authority = authority_;
                  LogSetAuthority(authority);
              }
          
              modifier auth {
                  assert(isAuthorized(msg.sender, msg.sig));
                  _;
              }
          
              modifier authorized(bytes4 sig) {
                  assert(isAuthorized(msg.sender, sig));
                  _;
              }
          
              function isAuthorized(address src, bytes4 sig) internal returns (bool) {
                  if (src == address(this)) {
                      return true;
                  } else if (src == owner) {
                      return true;
                  } else if (authority == DSAuthority(0)) {
                      return false;
                  } else {
                      return authority.canCall(src, this, sig);
                  }
              }
          
              function assert(bool x) internal {
                  if (!x) throw;
              }
          }
          
          contract DSNote {
              event LogNote(
                  bytes4   indexed  sig,
                  address  indexed  guy,
                  bytes32  indexed  foo,
                  bytes32  indexed  bar,
          	uint	 	  wad,
                  bytes             fax
              ) anonymous;
          
              modifier note {
                  bytes32 foo;
                  bytes32 bar;
          
                  assembly {
                      foo := calldataload(4)
                      bar := calldataload(36)
                  }
          
                  LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
          
                  _;
              }
          }
          
          contract DSMath {
              
              /*
              standard uint256 functions
               */
          
              function add(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  assert((z = x + y) >= x);
              }
          
              function sub(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  assert((z = x - y) <= x);
              }
          
              function mul(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  assert((z = x * y) >= x);
              }
          
              function div(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  z = x / y;
              }
          
              function min(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  return x <= y ? x : y;
              }
              function max(uint256 x, uint256 y) constant internal returns (uint256 z) {
                  return x >= y ? x : y;
              }
          
              /*
              uint128 functions (h is for half)
               */
          
          
              function hadd(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  assert((z = x + y) >= x);
              }
          
              function hsub(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  assert((z = x - y) <= x);
              }
          
              function hmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  assert((z = x * y) >= x);
              }
          
              function hdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  z = x / y;
              }
          
              function hmin(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  return x <= y ? x : y;
              }
              function hmax(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  return x >= y ? x : y;
              }
          
          
              /*
              int256 functions
               */
          
              function imin(int256 x, int256 y) constant internal returns (int256 z) {
                  return x <= y ? x : y;
              }
              function imax(int256 x, int256 y) constant internal returns (int256 z) {
                  return x >= y ? x : y;
              }
          
              /*
              WAD math
               */
          
              uint128 constant WAD = 10 ** 18;
          
              function wadd(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hadd(x, y);
              }
          
              function wsub(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hsub(x, y);
              }
          
              function wmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  z = cast((uint256(x) * y + WAD / 2) / WAD);
              }
          
              function wdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  z = cast((uint256(x) * WAD + y / 2) / y);
              }
          
              function wmin(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hmin(x, y);
              }
              function wmax(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hmax(x, y);
              }
          
              /*
              RAY math
               */
          
              uint128 constant RAY = 10 ** 27;
          
              function radd(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hadd(x, y);
              }
          
              function rsub(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hsub(x, y);
              }
          
              function rmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  z = cast((uint256(x) * y + RAY / 2) / RAY);
              }
          
              function rdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
                  z = cast((uint256(x) * RAY + y / 2) / y);
              }
          
              function rpow(uint128 x, uint64 n) constant internal returns (uint128 z) {
                  // This famous algorithm is called "exponentiation by squaring"
                  // and calculates x^n with x as fixed-point and n as regular unsigned.
                  //
                  // It's O(log n), instead of O(n) for naive repeated multiplication.
                  //
                  // These facts are why it works:
                  //
                  //  If n is even, then x^n = (x^2)^(n/2).
                  //  If n is odd,  then x^n = x * x^(n-1),
                  //   and applying the equation for even x gives
                  //    x^n = x * (x^2)^((n-1) / 2).
                  //
                  //  Also, EVM division is flooring and
                  //    floor[(n-1) / 2] = floor[n / 2].
          
                  z = n % 2 != 0 ? x : RAY;
          
                  for (n /= 2; n != 0; n /= 2) {
                      x = rmul(x, x);
          
                      if (n % 2 != 0) {
                          z = rmul(z, x);
                      }
                  }
              }
          
              function rmin(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hmin(x, y);
              }
              function rmax(uint128 x, uint128 y) constant internal returns (uint128) {
                  return hmax(x, y);
              }
          
              function cast(uint256 x) constant internal returns (uint128 z) {
                  assert((z = uint128(x)) == x);
              }
          
          }
          
          contract DSThing is DSAuth, DSNote, DSMath {
          }
          
          contract DSValue is DSThing {
              bool    has;
              bytes32 val;
              function peek() constant returns (bytes32, bool) {
                  return (val,has);
              }
              function read() constant returns (bytes32) {
                  var (wut, has) = peek();
                  assert(has);
                  return wut;
              }
              function poke(bytes32 wut) note auth {
                  val = wut;
                  has = true;
              }
              function void() note auth { // unset the value
                  has = false;
              }
          }
          
          contract Medianizer is DSValue {
              mapping (bytes12 => address) public values;
              mapping (address => bytes12) public indexes;
              bytes12 public next = 0x1;
          
              uint96 public min = 0x1;
          
              function set(address wat) auth {
                  bytes12 nextId = bytes12(uint96(next) + 1);
                  assert(nextId != 0x0);
                  set(next, wat);
                  next = nextId;
              }
          
              function set(bytes12 pos, address wat) note auth {
                  if (pos == 0x0) throw;
          
                  if (wat != 0 && indexes[wat] != 0) throw;
          
                  indexes[values[pos]] = 0; // Making sure to remove a possible existing address in that position
          
                  if (wat != 0) {
                      indexes[wat] = pos;
                  }
          
                  values[pos] = wat;
              }
          
              function setMin(uint96 min_) note auth {
                  if (min_ == 0x0) throw;
                  min = min_;
              }
          
              function setNext(bytes12 next_) note auth {
                  if (next_ == 0x0) throw;
                  next = next_;
              }
          
              function unset(bytes12 pos) {
                  set(pos, 0);
              }
          
              function unset(address wat) {
                  set(indexes[wat], 0);
              }
          
              function poke() {
                  poke(0);
              }
          
              function poke(bytes32) note {
                  (val, has) = compute();
              }
          
              function compute() constant returns (bytes32, bool) {
                  bytes32[] memory wuts = new bytes32[](uint96(next) - 1);
                  uint96 ctr = 0;
                  for (uint96 i = 1; i < uint96(next); i++) {
                      if (values[bytes12(i)] != 0) {
                          var (wut, wuz) = DSValue(values[bytes12(i)]).peek();
                          if (wuz) {
                              if (ctr == 0 || wut >= wuts[ctr - 1]) {
                                  wuts[ctr] = wut;
                              } else {
                                  uint96 j = 0;
                                  while (wut >= wuts[j]) {
                                      j++;
                                  }
                                  for (uint96 k = ctr; k > j; k--) {
                                      wuts[k] = wuts[k - 1];
                                  }
                                  wuts[j] = wut;
                              }
                              ctr++;
                          }
                      }
                  }
          
                  if (ctr < min) return (val, false);
          
                  bytes32 value;
                  if (ctr % 2 == 0) {
                      uint128 val1 = uint128(wuts[(ctr / 2) - 1]);
                      uint128 val2 = uint128(wuts[ctr / 2]);
                      value = bytes32(wdiv(hadd(val1, val2), 2 ether));
                  } else {
                      value = wuts[(ctr - 1) / 2];
                  }
          
                  return (value, true);
              }
          
          }