Back to Home

globalregistrar

Token
0x33990122638b...37f1a891a70c
FrontierSource Verified
Deployed September 24, 2015 (10 years ago)Block 282,880

The canonical name registration contract hardcoded into go-ethereum — Ethereum's first mainnet naming system, mapping human-readable strings to addresses. A dir...

Key Facts

Deployment Block
282,880
Deployment Date
Sep 24, 2015, 11:06 AM
Code Size
2.8 KB
Transactions by Year
2015305
20169,063
20211
20221,779
20256

Description

Deployed on September 24, 2015 (block 282,880, ~55 days after Frontier launch), the GlobalRegistrar was Ethereum's first on-chain name registry. It maps human-readable strings to Ethereum addresses, enabling the go-ethereum client to resolve names like "HashReg" and "UrlHint" to their deployed contract addresses on mainnet.

The contract was deployed by a go-ethereum core developer and immediately hardcoded into the go-ethereum client as GlobalRegistrarAddr = "0x33990122638b9132ca29c723bdf037f1a891a70c" // frontier in the file common/registrar/registrar.go. It forms part of a three-contract name resolution system embedded in go-ethereum:

  1. GlobalRegistrar (this contract): Name string → Address (Owner)
  2. HashReg (0x23bf622b5a65f6060d855fca401133ded3520620): Key Hash → Content Hash
  3. UrlHint (0x73ed5ef6c010727dfd2671dbb70faac19ec18626): Content Hash → URL Hint

This infrastructure powered go-ethereum's NatSpec documentation system (which linked contract ABIs to human-readable documentation via on-chain URLs) and its eth:// URL resolver. Within blocks of deploying the GlobalRegistrar, the deployer called reserve() to register both "HashReg" and "UrlHint" — bootstrapping the naming system so that go-ethereum could locate the other infrastructure contracts automatically.

The full Solidity source code was later verified on Etherscan (compiled with solc v0.1.1). It includes a notable comment frozen into the code: "TODO: bidding mechanism" — revealing that a name auction system was planned but never implemented. This gap in the design was later addressed by ENS (Ethereum Name Service), which launched in 2017 and introduced a complete auction-based name registration system. The GlobalRegistrar's successor architecture directly influenced ENS.

The deployer registered the contract under the names that go-ethereum's codebase expected, ensuring every geth user from 2015 onward was interacting with this specific on-chain deployment when resolving names or accessing NatSpec documentation.

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

This contract has verified source code on Etherscan.

View Source Code
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