ETH Price: $2,438.04 (+0.14%)

Transaction Decoder

Block:
22806623 at Jun-29-2025 12:50:47 AM +UTC
Transaction Fee:
0.000037597407005676 ETH $0.09
Gas Used:
108,241 Gas / 0.347349036 Gwei

Emitted Events:

226 Deed.DeedClosed( )
227 Registrar.HashReleased( hash=2C7661A1B99B1700078688B64CD264172F8C3BB6284C9394B3DD8485226804C5, value=0 )
228 0xf08ced2be13cb9a12793da7ef6e23207b049af83.0x8de43d9a73b67cd262221606ac0627d14cbcfa306b96d16bd9e20e72771cb4ed( 0x8de43d9a73b67cd262221606ac0627d14cbcfa306b96d16bd9e20e72771cb4ed, 0x0000000000000000000000006090a6e47849629b7245dfa1ca21d94cd15878ef, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000001 )
229 0xf08ced2be13cb9a12793da7ef6e23207b049af83.0x8de43d9a73b67cd262221606ac0627d14cbcfa306b96d16bd9e20e72771cb4ed( 0x8de43d9a73b67cd262221606ac0627d14cbcfa306b96d16bd9e20e72771cb4ed, 0x000000000000000000000000f08ced2be13cb9a12793da7ef6e23207b049af83, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000001 )
230 0xf08ced2be13cb9a12793da7ef6e23207b049af83.0xe9cc9bbe7de1cbb097a6357ca3182909488efe8d793e25665befc064a02d10a7( 0xe9cc9bbe7de1cbb097a6357ca3182909488efe8d793e25665befc064a02d10a7, 0x0000000000000000000000000000000000000000000000000000000000000002 )

Account State Difference:

  Address   Before After State Difference Code
0x5999F511...7f7946a25 0.01 Eth0 Eth0.01
0x6090A6e4...cd15878Ef
(ENS: Old Registrar)
0x76e3D82B...0Ba23740d
0.015499146811756901 Eth
Nonce: 3392
0.015461549404751225 Eth
Nonce: 3393
0.000037597407005676
(beaverbuild)
28.333068319655118856 Eth28.333072725510096499 Eth0.000004405854977643
0xE2dC4277...fA16647B3 0.510210874865891841 Eth0.520210874865891841 Eth0.01
0xF08Ced2B...7b049AF83

Execution Trace

0xf08ced2be13cb9a12793da7ef6e23207b049af83.0b51f8d5( )
  • Registrar.releaseDeed( _hash=2C7661A1B99B1700078688B64CD264172F8C3BB6284C9394B3DD8485226804C5 )
    • Deed.CALL( )
    • ENS.owner( node=93CDEB708B7545DC668EB9280176169D1C33CFD8ED6F04690A0BCC88A93FC4AE ) => ( 0x6109DD117AA5486605FC85e040ab00163a75c662 )
    • Deed.closeDeed( refundRatio=1000 )
      • Null: 0x00...dEaD.CALL( )
      • ETH 0.01 0xf08ced2be13cb9a12793da7ef6e23207b049af83.CALL( )
      • Null: 0x00...dEaD.SELFDESTRUCT( )
      • 0xf08ced2be13cb9a12793da7ef6e23207b049af83.df025ec6( )
        • ETH 0.01 0xe2dc4277451c95261d56637ae0692f5fa16647b3.CALL( )
          File 1 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) {}
          
          }

          File 2 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 3 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))) 
           
          )