ETH Price: $2,550.57 (+3.14%)

Transaction Decoder

Block:
4428149 at Oct-25-2017 05:29:09 PM +UTC
Transaction Fee:
0.009603699 ETH $24.49
Gas Used:
457,319 Gas / 21 Gwei

Emitted Events:

6 Registrar.AuctionStarted( hash=FCAD85C5739ECDAF07F25932075FA89DEE624F41DD80DE5D2CE0A77C6EFF716E, registrationDate=1509384549 )
7 Registrar.NewBid( hash=B30878ABE3BC959C4FED416D9404E2EAF8F80BD13359FC4F302F28C13F4D9A84, bidder=[Sender] 0x3ffc07ed6a65e379e39bef93e713ee3ff77a56e4, deposit=490000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x3FfC07ED...Ff77a56e4
0.994118 Eth
Nonce: 0
0.494514301 Eth
Nonce: 1
0.499603699
0x6090A6e4...cd15878Ef
(ENS: Old Registrar)
0x7940f15F...d177BF318
0 Eth
Nonce: 0
0.49 Eth
Nonce: 1
0.49From: 0 To: 2405967547298229508834657506165309200074358835307327951622245925003065681782105322477705305281306687888611625774821655491402639513940395941737169615280630520171395857781323478743309263262434737301020800582682193257532537614975590106845735898838957271819256358953469163735036940221192051639156912354865418586664226151856895164375228600716489980758824610799036596865511485357416250944898798084578923646470532198943906139796212600243811224068255485757391849051012207179118366088959440603954263741908108163848591725663972696508100252421367627632329824083016646113608275621982645513532757186411882839445867634939562230288952166593649760923763766100249519669452032361708400870313530123273112067581969135210131084302405077504507129721996042641030574772195832854740990708989916427907187118662084348864603922007910947023583136602526267385801882609991738738603859837541327483857704998551970083593034678915991764213597461090852626797884264943128534562365636314027649977898834190965022484807845762496571676931902544808169417708330345406968215134040914072162358512060567589428154601776423480296369868316165074761399503330131660991879321401773340351701598706505161226735686932130768495486376101349019099853576105085720469905627719520581778166051887402034817675978033624266888082192114079284906392985221053497333639516868925048835643291547563982581736476497029343510355713922643417878493611713181853007934489248133881235052838544550330427221226863110855736816868454255030087742171763360699198389768660266344915182343450266888387139915223433528561542459028960347965468969513212276510878266092508576793149030708300327999347442848230024454189978746984928885111858404689649487799629031587962912475475657004061354779705486890981350293050286022146411917630075473512135412774861466305201648005111261240055485690693998538627430727621319319524292416556595477590175055292979452206696288262351987909614482652801362882704543599160007586238983645137019303778634592378504263521685999529960511913206706005265071678698737213996116819356099198223460450865761979857330030724506392829558027407724746046457469303648518147019281928550863352819035642369367559382481618473519198783188153524676355186725422122149170411971542339917579231182197513430591497807305867702532047333370155071884027416011604931953915754646385276419579961282925920024871736176351501394051428731349647247251392574240978208345665361607385472963296146284339065100302076402445881391394172187666348494468718445439627550501543258883840382636350618559074473772053665929829408955277275318222412710249479354143953432480224200243760712961069828119356568813905563033312379196257078373830994657811456216211738836798067716065556815874824100607376647800237073321669185452692931438311315123970353014036113295052788165660359003193736549472816126213000204466998446302965203526379874737917769532147036696312292311796372093177637423789856808661942313
(Ethermine)
699.884607315521082965 Eth699.894211014521082965 Eth0.009603699

Execution Trace

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

    File 3 of 3: 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) {}
    
    }