ETH Price: $2,420.11 (-0.69%)

Transaction Decoder

Block:
7836407 at May-26-2019 04:53:16 PM +UTC
Transaction Fee:
0.000023547 ETH $0.06
Gas Used:
78,490 Gas / 0.3 Gwei

Emitted Events:

61 Deed.DeedClosed( )
62 BaseRegistrarImplementation.Transfer( from=0x00000000...000000000, to=[Sender] 0x26de4b5211b568264a4018682595718e02aae7c2, tokenId=14210197849962831813894520552364818131403290555951078055296772047092661875546 )
63 ENS.NewOwner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE, label=1F6AAFDCACF8E907900F0B8D9BD5DED789366E1A1B7747C9DD3AE27F89FBF35A, owner=[Sender] 0x26de4b5211b568264a4018682595718e02aae7c2 )
64 BaseRegistrarImplementation.NameMigrated( id=14210197849962831813894520552364818131403290555951078055296772047092661875546, owner=[Sender] 0x26de4b5211b568264a4018682595718e02aae7c2, expires=1588550400 )
65 BaseRegistrarImplementation.NameRegistered( id=14210197849962831813894520552364818131403290555951078055296772047092661875546, owner=[Sender] 0x26de4b5211b568264a4018682595718e02aae7c2, expires=1588550400 )

Account State Difference:

  Address   Before After State Difference Code
0x26dE4b52...e02AaE7C2
24.65017563127298394 Eth
Nonce: 1409
24.66015208427298394 Eth
Nonce: 1410
0.009976453
0x6090A6e4...cd15878Ef
(ENS: Old Registrar)
0x6Bf8dE9C...56491afA4
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
(MiningPoolHub: Old Address)
9,059.356538189493795158 Eth9,059.356561736493795158 Eth0.000023547
0xFaC7BEA2...556b31e04

Execution Trace

Registrar.transferRegistrars( _hash=1F6AAFDCACF8E907900F0B8D9BD5DED789366E1A1B7747C9DD3AE27F89FBF35A )
  • Deed.CALL( )
  • ENS.owner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE ) => ( 0xFaC7BEA255a6990f749363002136aF6556b31e04 )
  • Deed.setRegistrar( newRegistrar=0xFaC7BEA255a6990f749363002136aF6556b31e04 )
  • BaseRegistrarImplementation.acceptRegistrarTransfer( label=1F6AAFDCACF8E907900F0B8D9BD5DED789366E1A1B7747C9DD3AE27F89FBF35A, deed=0x6Bf8dE9C87F7350a0C770E74DA2343956491afA4, 1499335614 )
    • ENS.owner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE ) => ( 0xFaC7BEA255a6990f749363002136aF6556b31e04 )
    • Registrar.entries( _hash=1F6AAFDCACF8E907900F0B8D9BD5DED789366E1A1B7747C9DD3AE27F89FBF35A ) => ( 2, 0x6Bf8dE9C87F7350a0C770E74DA2343956491afA4, 1499335614, 10000000000000000, 10000000000000000 )
    • Deed.STATICCALL( )
    • Deed.closeDeed( refundRatio=1000 )
      • Null: 0x00...dEaD.CALL( )
      • ETH 0.01 0x26de4b5211b568264a4018682595718e02aae7c2.CALL( )
      • Null: 0x00...dEaD.SELFDESTRUCT( )
      • ENS.setSubnodeOwner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE, label=1F6AAFDCACF8E907900F0B8D9BD5DED789366E1A1B7747C9DD3AE27F89FBF35A, owner=0x26dE4b5211b568264a4018682595718e02AaE7C2 )
        transferRegistrars[Registrar (ln:578)]
        File 1 of 4: 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 2 of 4: Deed
        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 3 of 4: 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 4 of 4: 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))) 
         
        )