Back to Home

globalregistrar

Token
0xaefd94f2b04b...e415bff061c0
FrontierContract #318Source VerifiedEdit this contract
Deployed August 19, 2015 (10 years ago)Block 110,226

The ninth iteration of the GlobalRegistrar contract, which became the canonical Ethereum name registrar hardcoded into Geth and other clients during the Frontie

Key Facts

Deployment Block
110,226
Deployment Date
Aug 19, 2015, 07:42 AM
Code Size
2.8 KB
Gas at Deploy
779,965
Transactions by Year
202236

Description

The GlobalRegistrar contract (deployed at block 110,226 on August 19, 2015) served as Ethereum's first persistent, on-chain name resolution system. It implemented a hierarchical naming architecture through which any account could reserve a human-readable name and associate it with an address, a sub-registrar, or arbitrary content hash. Names were first-come, first-served: once a bytes32 identifier was claimed, only the owner could transfer or disown it. The contract was compiled with Solidity v0.1.1—one of the earliest released compiler versions—and authored in the style of the canonical dapp-bin examples maintained by the Ethereum Foundation.

This deployment (sometimes called version 9, or "v9") is notable for being the instance that was eventually hardcoded into the go-ethereum (Geth) client as the official registrar address. Prior to this, users had to manually load the registrar address each session; after the hardcoding, eth.namereg pointed directly to this contract by default, making it the de-facto human-name layer for the Frontier network.

The contract sits within a lineage of 19 nearly-identical deployments of the same source code—ranging from the very first deployment by Linagee (v0, block 51,807) through several intermediate versions—as the Ethereum community converged on a single authoritative instance. Each earlier iteration was rendered obsolete once the community adopted v9. The source code itself left room for a planned but never-implemented auction mechanism for short names, visible in the inline TODO comments, a window into the rapid, iterative development culture of the early Ethereum ecosystem.

Historically, the GlobalRegistrar represents the first attempt at a decentralized naming service on Ethereum, pre-dating the Ethereum Name Service (ENS) by roughly two years. Where ENS later introduced a fully decentralised auction and resolver architecture, the GlobalRegistrar operated on simple first-come-first-served reservation and manual address association.

Source Verified

Etherscan verified

Heuristic Analysis

The following characteristics were detected through bytecode analysis and may not be accurate.

Detected Type: Token

Frontier Era

The initial release of Ethereum. A bare-bones implementation for technical users.

Block span: 01,149,999
July 30, 2015March 14, 2016

Bytecode Overview

Opcodes2,894
Unique Opcodes147
Jump Instructions72
Storage Operations62

Verified Source Available

Source verified on Etherscan.

Show source code (Solidity)
contract NameRegister {
  function addr(bytes32 _name) constant returns (address o_owner) {}
  function name(address _owner) constant returns (bytes32 o_name) {}
}
contract Registrar is NameRegister {
  event Changed(bytes32 indexed name);
  event PrimaryChanged(bytes32 indexed name, address indexed addr);
  function owner(bytes32 _name) constant returns (address o_owner) {}
  function addr(bytes32 _name) constant returns (address o_address) {}
  function subRegistrar(bytes32 _name) constant returns (address o_subRegistrar) {}
  function content(bytes32 _name) constant returns (bytes32 o_content) {}
  function name(address _owner) constant returns (bytes32 o_name) {}
}

contract GlobalRegistrar is Registrar {
  struct Record {
    address owner;
    address primary;
    address subRegistrar;
    bytes32 content;
    uint value;
    uint renewalDate;
  }
  function Registrar() {
    // TODO: Populate with hall-of-fame.
  }
  function reserve(bytes32 _name) {
    // Don't allow the same name to be overwritten.
    // TODO: bidding mechanism
    if (m_toRecord[_name].owner == 0) {
      m_toRecord[_name].owner = msg.sender;
      Changed(_name);
    }
  }
  /*
  TODO
  > 12 chars: free
  <= 12 chars: auction:
  1. new names are auctioned
  - 7 day period to collect all bid bytes32es + deposits
  - 1 day period to collect all bids to be considered (validity requires associated deposit to be >10% of bid)
  - all valid bids are burnt except highest - difference between that and second highest is returned to winner
  2. remember when last auctioned/renewed
  3. anyone can force renewal process:
  - 7 day period to collect all bid bytes32es + deposits
  - 1 day period to collect all bids & full amounts - bids only uncovered if sufficiently high.
  - 1% of winner burnt; original owner paid rest.
  */
  modifier onlyrecordowner(bytes32 _name) { if (m_toRecord[_name].owner == msg.sender) _ }
  function transfer(bytes32 _name, address _newOwner) onlyrecordowner(_name) {
    m_toRecord[_name].owner = _newOwner;
    Changed(_name);
  }
  function disown(bytes32 _name) onlyrecordowner(_name) {
    if (m_toName[m_toRecord[_name].primary] == _name)
    {
      PrimaryChanged(_name, m_toRecord[_name].primary);
      m_toName[m_toRecord[_name].primary] = "";
    }
    delete m_toRecord[_name];
    Changed(_name);
  }
  function setAddress(bytes32 _name, address _a, bool _primary) onlyrecordowner(_name) {
    m_toRecord[_name].primary = _a;
    if (_primary)
    {
      PrimaryChanged(_name, _a);
      m_toName[_a] = _name;
    }
    Changed(_name);
  }
  function setSubRegistrar(bytes32 _name, address _registrar) onlyrecordowner(_name) {
    m_toRecord[_name].subRegistrar = _registrar;
    Changed(_name);
  }
  function setContent(bytes32 _name, bytes32 _content) onlyrecordowner(_name) {
    m_toRecord[_name].content = _content;
    Changed(_name);
  }
  function owner(bytes32 _name) constant returns (address) { return m_toRecord[_name].owner; }
  function addr(bytes32 _name) constant returns (address) { return m_toRecord[_name].primary; }
//  function subRegistrar(bytes32 _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } // TODO: bring in on next iteration.
  function register(bytes32 _name) constant returns (address) { return m_toRecord[_name].subRegistrar; }  // only possible for now
  function content(bytes32 _name) constant returns (bytes32) { return m_toRecord[_name].content; }
  function name(address _owner) constant returns (bytes32 o_name) { return m_toName[_owner]; }
  mapping (address => bytes32) m_toName;
  mapping (bytes32 => Record) m_toRecord;
}

External Links