Base Registrar & Controller
The Base Registrar manages the .vet
name space within an on-chain registy and the Registrar Controller allows trustless on-chain name registration by everyone.
Commit Reveal
The Registrar Controller implements a commit reveal scheme to prevent frontrunning.
The way it works is that during the registration process we first call the commit
function with an opaque bit of data (the commitmenthash
).
Wait one blocks and then call the register
function.
The commit
function takes a commitment hash, which can be generated using the makeCommitment
function. The commitment hash is opaque and revealed during the register
function.
The commit reveal process ensures no eavesdropping third-party is able to register your name before you can.
RegistrarController.makeCommitment(name string, owner address, duration uint256, secret bytes32, resolver address, data bytes[], reverseRecord bool, ownerControlledFuses uint16)
// For example
makeCommitment(
"hello", // "hello.vet" but only the label
0x1234..., // The address you want to own the name
31536000, // 1 year (in seconds)
0x1234..., // A secret that you have generated (32 bytes)
0x1234..., // The address of the resolver you want to use
[],
false, // Set as primary name?
0
);
Once you have calculated the commitment hash you can call the commit
function.
RegistrarController.commit(commitment bytes32)
Note this does require an on-chain transaction.
After having committed it is recommended to wait at least the MIN_COMMITMENT_AGE
(~10 seconds) before registering.
Registering
Once you have committed you can register your name.
Registration takes in the same parameters as the makeCommitment
function, but this time is in the form of a transaction.
Before initiating registration ensure that:
available(name)
== trueduration
>=MIN_REGISTRATION_DURATION
commitments[commitment]
is between 1 min and 24 hrs oldmsg.value
>=rentPrice(name, duration)
RegistrarController.register(name string, owner address, duration uint256, secret bytes32, resolver address, data bytes[], reverseRecord bool, ownerControlledFuses uint16)
// For example
register(
"hello", // "hello.vet" but only the label
0x1234..., // The address you want to own the name
31536000, // 1 year (in seconds)
0x1234..., // A secret that you have generated (32 bytes)
0x1234..., // The address of the resolver you want to use
[],
false, // Set as primary name?
0
);
Renewing a Name
RegistrarController.renew()
Any user, not solely the owner, has the capability to renew a domain. This enables you to renew a domain on behalf of someone else to prevent its expiration.
The system permits renewals for any chosen duration, ensuring that domain names remain active. Despite any updates to the controller, the separation between the registry and controller guarantees that your domain remains under your ownership.
Interface
pragma solidity >=0.8.4;
interface IRegistrarController {
// Error to indicate the commitment is too new
error CommitmentTooNew(bytes32);
// Error to indicate the commitment is too old
error CommitmentTooOld(bytes32);
// Error to indicate the duration is too short
error DurationTooShort(uint256);
// Error to indicate the value sent with the transaction is insufficient
error InsufficientValue();
// Error to indicate the maximum commitment age is too high
error MaxCommitmentAgeTooHigh();
// Error to indicate the maximum commitment age is too low
error MaxCommitmentAgeTooLow();
// Error to indicate the name is not available for registration
error NameNotAvailable(string);
// Error to indicate a resolver is required when data is supplied
error ResolverRequiredWhenDataSupplied();
// Error to indicate an unexpired commitment exists
error UnexpiredCommitmentExists(bytes32);
// Event emitted when a name is registered
event NameRegistered(string,bytes32 indexed,address indexed,uint256,uint256,uint256);
// Event emitted when a name is renewed
event NameRenewed(string,bytes32 indexed,uint256,uint256);
// Function to get the minimum registration duration
function MIN_REGISTRATION_DURATION() view returns (uint256);
// Function to check if a name is available for registration
function available(string) view returns (bool);
// Function to commit a name registration
function commit(bytes32);
// Function to get the timestamp of a commitment
function commitments(bytes32) view returns (uint256);
// Function to make a commitment to register a name
function makeCommitment(string,address,uint256,bytes32,address,bytes[],bool,uint16) pure returns (bytes32);
// Function to get the maximum commitment age
function maxCommitmentAge() view returns (uint256);
// Function to get the minimum commitment age
function minCommitmentAge() view returns (uint256);
// Function to get the address of the name wrapper contract
function nameWrapper() view returns (address);
// Function to get the address of the prices contract
function prices() view returns (address);
// Function to register a name
function register(string,address,uint256,bytes32,address,bytes[],bool,uint16) payable;
// Function to renew a name registration
function renew(string,uint256) payable;
// Function to get the rent price for a name
function rentPrice(string,uint256) view returns (tuple(uint256,uint256));
// Function to get the address of the reverse registrar contract
function reverseRegistrar() view returns (address);
// Function to check if the contract supports an interface
function supportsInterface(bytes4) pure returns (bool);
// Function to check if a string is a valid name
function valid(string) pure returns (bool);
// Function to withdraw funds from the contract
function withdraw();
}
pragma solidity >=0.8.4;
interface IBaseRegistrar {
// Emitted when a token is approved to another address
event Approval(address indexed, address indexed, uint256 indexed);
// Emitted when an operator is approved or disapproved for all tokens
event ApprovalForAll(address indexed, address indexed, bool);
// Emitted when a name is migrated to a new registrar
event NameMigrated(uint256 indexed, address indexed, uint256);
// Emitted when a name is registered
event NameRegistered(uint256 indexed, address indexed, uint256);
// Emitted when a name is renewed
event NameRenewed(uint256 indexed, uint256);
// Emitted when a token is transferred from one address to another
event Transfer(address indexed, address indexed, uint256 indexed);
// Returns the grace period for renewals
function GRACE_PERIOD() external view returns (uint256);
// Approves a token to an address
function approve(address, uint256);
// Checks if a name is available for registration
function available(uint256) external view returns (bool);
// Returns the balance of an address
function balanceOf(address) external view returns (uint256);
// Returns the base node of the registrar
function baseNode() external view returns (bytes32);
// Returns the address of the registry
function ens() external view returns (address);
// Returns the approved address for a token
function getApproved(uint256) external view returns (address);
// Checks if an operator is approved for all tokens of an owner
function isApprovedForAll(address, address) external view returns (bool);
// Returns the name associated with the registrar
function name() external view returns (string);
// Returns the expiration date of a name
function nameExpires(uint256) external view returns (uint256);
// Returns the owner of a token
function ownerOf(uint256) external view returns (address);
// Reclaims a name to an address
function reclaim(uint256, address);
// Registers a name
function register(uint256, address, uint256) external returns (uint256);
// Registers a name, only if it's available
function registerOnly(uint256, address, uint256) external returns (uint256);
// Renews a name
function renew(uint256, uint256) external returns (uint256);
// Safely transfers a token from one address to another
function safeTransferFrom(address, address, uint256);
// Safely transfers a token from one address to another with additional data
function safeTransferFrom(address, address, uint256, bytes calldata);
// Sets or unsets an operator for all tokens
function setApprovalForAll(address, bool);
// Sets the resolver for the base node
function setResolver(address);
// Checks if the contract implements an interface
function supportsInterface(bytes4) external view returns (bool);
// Returns the symbol of the registrar
function symbol() external view returns (string);
// Returns the URI of a token
function tokenURI(uint256) external view returns (string);
// Transfers a token from one address to another
function transferFrom(address, address, uint256);
}