The official Ethereum GlobalRegistrar deployed by the go-ethereum team in August 2015. This was the canonical name registry contract embedded as pre-compiled by
Key Facts
Description
The official Ethereum GlobalRegistrar, deployed at block 50,466 (August 13, 2015) by 0x3d0768da09. This is the canonical name registry pre-compiled by the Ethereum Foundation and embedded as GlobalRegistrarCode in go-ethereum's common/registrar/contracts.go (commit 83ee39448e, June 23, 2015). The deployer used go-ethereum's built-in --registrar deployment tool, which sent the embedded bytecode directly - no independent compilation required. The contract maps bytes32 names to owners, addresses, sub-registrars, and content hashes. It implements the full Registrar interface with 13 functions including reserve, transfer, disown, setAddress, and setContent. Notably, register(bytes32) is a temporary alias returning the sub-registrar address (the canonical subRegistrar() getter is commented out in source with a 'TODO: bring in on next iteration' note). The same bytecode was also deployed at block 51,245 (0xf436ceba) by the same developer.
Source Verified
Bytecode pre-compiled and embedded in go-ethereum commit 83ee39448e. Creation TX input matches GlobalRegistrarCode constant byte-for-byte.
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Verification ProofShow source code (Solidity)
//sol
import "owned";
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;
}