DotnsRegistrarController

Git Source

Inherits: Initializable, UUPSUpgradeable, DotnsRoleManager, ReentrancyGuardTransient, IDotnsRegistrarController

Title: Dotns Registrar Controller

Allocates .dot labels using a commit reveal scheme.

Orchestrates allocation, PoP validation, pricing enforcement, forward registry wiring, default reverse resolution, and immutable store writing. Tokenisation: the minted ERC721 tokenId is uint256(node), where node = namehash(DOT_NODE, labelhash). The registry stores a sentinel owner (address(0)) for tokenised nodes and derives ownership from the ERC721 registrar for authorisation.

Note: security-contact: admin@parity.io

Constants

MAX_ALLOWED_COMMITMENT_AGE

Upper bound for commitment validity to cap storage griefing risk.

uint256 public constant MAX_ALLOWED_COMMITMENT_AGE = 7 days

State Variables

minCommitmentAge

Minimum age a commitment must reach before reveal.

uint256 public minCommitmentAge

maxCommitmentAge

Maximum age after which a commitment expires.

uint256 public maxCommitmentAge

commitments

Stores Mapping of commitment hashes to timestamp committed.

mapping(bytes32 hash => uint256 timestamp) public commitments

whiteList

Whitelist for addresses allowed to call registerReserved.

mapping(address user => bool isWhiteListed) public whiteList

protocolRegistry

Protocol-level address registry for all DotNS contracts.

IDotnsProtocolRegistry public protocolRegistry

__gap

Reserved storage space to allow for layout changes in the future.

uint256[50] private __gap

Functions

onlyWhiteListedOrOwner

Restricts calls to whitelisted addresses or the owner.

Used to gate registerReserved, which allows registering reserved names without PoP checks or payment. Necessary so the owner (or a whitelisted operator) can seed reserved names on behalf of users who are already known and verified and do not need PoP checks.

modifier onlyWhiteListedOrOwner() ;

onlyWhitelistOperatorOrOwner

modifier onlyWhitelistOperatorOrOwner() ;

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initialises the registrar controller.

Callable once through the UUPS proxy; direct calls on the implementation revert with @custom:reverts InvalidInitialization, and any nested call outside an active initialiser scope reverts with @custom:reverts NotInitializing. Validates the commitment window bounds: minAge must be strictly positive (otherwise

Notes:

  • reverts: MinCommitmentAgeZero) so a reveal cannot land in the same block as its commit; maxAge must exceed minAge (otherwise

  • reverts: MaxCommitmentAgeTooLow) and must stay within MAX_ALLOWED_COMMITMENT_AGE (otherwise @custom:reverts MaxCommitmentAgeTooHigh) before wiring the protocol registry.

function initialize(
    IDotnsProtocolRegistry registry,
    uint256 minAge,
    uint256 maxAge
)
    external
    initializer;

available

Returns whether a label is available for registration.

Validates the canonical DNS-label shape (otherwise @custom:reverts InvalidLabel) and rejects labels below the minimum-length policy with

Note: reverts: LabelTooShort before checking ERC721 availability on the registrar.

function available(string calldata label) public view override returns (bool);

makeCommitment

Computes the commitment hash for a registration.

Uses abi.encode so the variable-width label is length-prefixed and the boundary between label and the fixed-width owner, secret, and reserved fields is unambiguous, binding the commitment to the exact tuple.

function makeCommitment(Registration calldata registration)
    public
    pure
    override
    returns (bytes32 commitment);

commit

Submits a commitment for a future registration.

Idempotent over expiry: re-committing an unexpired hash reverts with

Note: reverts: UnexpiredCommitmentExists (front-running guard); a hash whose stored timestamp has passed maxCommitmentAge overwrites the slot so storage cannot be permanently griefed. The expiry boundary is inclusive on the commit side (committedAt + maxCommitmentAge <= block.timestamp overwrites) and exclusive on the reveal side (register rejects at the same instant with @custom:reverts CommitmentTooOld), so the slot is overwritable from exactly the timestamp at which reveal begins rejecting it. Emits @custom:emits NameCommitted on success.

function commit(bytes32 commitment) external override;

register

Registers a name after the commitment delay.

Validates the label shape (otherwise @custom:reverts InvalidLabel), rejects labels below the minimum length policy (@custom:reverts LabelTooShort), and ERC721 availability (otherwise @custom:reverts NameNotAvailable), then consumes the prior commitment, which fails with @custom:reverts CommitmentNotFound when no commitment exists for the supplied registration, @custom:reverts CommitmentTooNew before minCommitmentAge, and

Note: reverts: CommitmentTooOld past maxCommitmentAge, and finally resolves the configured escrow address from the protocol registry (otherwise

function register(Registration calldata registration) external payable override nonReentrant;

_settleEscrow

Settles every escrow side-effect of a successful registration.

Extracted to keep register under the stack-depth ceiling. On a direct registration the full chargeAmount lands in the refundable deposit position keyed to nameOwner. On a cross-payer registration the deposit position is seeded with a zero amount so the release lifecycle stays reachable, and the same chargeAmount routes to the insurance fund via depositInsurance keyed to msg.sender as the payer.

function _settleEscrow(
    address escrow,
    uint256 tokenId,
    address nameOwner,
    bool isDirect,
    uint256 chargeAmount
)
    internal;

isWhiteListed

Checks if the given address is whitelisted to call registerReserved.

function isWhiteListed(address who) external view override returns (bool);

whiteListAddress

Adds or removes an address from the whitelist for registerReserved.

Callable by the owner or an account holding DotnsConstants.WHITELIST_OPERATOR_ROLE; any other caller reverts with @custom:reverts IDotnsRoleManager.NotRoleOrOwner. Emits

Note: emits: WhiteListed on success.

function whiteListAddress(
    address who,
    bool whiteListStatus
)
    external
    override
    onlyWhitelistOperatorOrOwner;

registerReserved

Registers a name after the commitment delay.

Whitelisted issuance path used to seed reserved labels at zero base cost: skips the PoP price check and the escrow deposit, but reuses the same commit-reveal pipeline so the same anti-front-running guarantees apply. Restricted to whitelisted callers and the owner (otherwise @custom:reverts NotWhiteListedOrOwner). Validates the label shape (otherwise @custom:reverts InvalidLabel) and ERC721 availability (otherwise

Notes:

  • reverts: NameNotAvailable), then consumes the prior commitment, which fails with

  • emits: NameRegistered on success.

function registerReserved(Registration calldata registration)
    external
    override
    onlyWhiteListedOrOwner
    nonReentrant;

supportsInterface

Returns true if this contract implements the interface defined by interfaceId. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.

function supportsInterface(bytes4 interfaceId)
    public
    view
    override(DotnsRoleManager, IERC165)
    returns (bool);

_validatedLabelNode

Validates label shape and derives (labelhash, node).

Delegates hashing to @custom:contract LabelUtils so the assembly sequence lives in exactly one place across the codebase. Error ownership stays on this interface: shape violations revert with InvalidLabel(); labels below the minimum length revert with LabelTooShort(label) so off-chain consumers can distinguish "shape-valid but below the policy minimum" from "shape-valid but already minted".

function _validatedLabelNode(string calldata label)
    internal
    pure
    returns (bytes32 labelhash, bytes32 node);

_requireAvailableLabel

function _requireAvailableLabel(string calldata label)
    internal
    view
    returns (IDotnsRegistrar registrar, bytes32 labelhash, bytes32 node);

_consumeCommitment

function _consumeCommitment(Registration calldata registration) internal;

_completeRegistration

Completes a commit-reveal registration: mints (or skips when reclaiming), wires forward registry, optionally sets the reverse record, and writes the owner's Store.

On a fresh mint the triad of mint + forward-registry + store-write is delegated to @custom:function RegistrationUtils.registerAndStore, the single canonical implementation shared across every DotNS registration flow. On a reclaim the mint step is skipped (the escrow has already moved custody) and only the registry wiring and store write run. Reverse-record setting and the priced-registration event stay here because they are commit-reveal-specific policy.

function _completeRegistration(
    Registration calldata registration,
    bytes32 labelhash,
    bytes32 node,
    uint256 baseCost,
    bool setReverseRecord,
    IDotnsReverseResolver reverse,
    bool isReclaim
)
    internal;

_escrow

Returns the configured name escrow from the protocol registry.

function _escrow() internal view returns (address escrow);

version

Returns implementation version.

function version() external pure virtual returns (string memory versionString);

Returns

NameTypeDescription
versionStringstringCurrent version string.

_onlyWhiteListedOrOwner

Internal check enforcing whitelist-or-owner access.

function _onlyWhiteListedOrOwner() internal view;

_isSupportedRole

function _isSupportedRole(bytes32 role) internal view override returns (bool supported);

_authorizeUpgrade

Function that should revert when msg.sender is not authorized to upgrade the contract. Called by {upgradeToAndCall}. Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.

function _authorizeUpgrade(address) internal onlyOwner {}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner;