DotnsRegistrarController

Git Source

Inherits: Initializable, UUPSUpgradeable, DotnsRoleManager, ReentrancyGuardTransient, IDotnsRegistrarController

Title: Dotns Registrar Controller

Allocates top-level 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(tldNode, 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

committedPricingVersion

Cost-model version stamped on a commitment at commit time.

Recorded from the registry's current version when commit runs, so the reveal can bind a registration to the version that was current then. A caller cannot commit against an arbitrary earlier, cheaper version: the reveal rejects a pricingVersion that differs from this stamp.

mapping(bytes32 hash => uint256 version) public committedPricingVersion

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[49] 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, reserved, maxPrice, and pricingVersion fields is unambiguous, binding the commitment to the exact tuple. The price ceiling and cost-model version are part of that tuple, so neither can be altered between commit and reveal.

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. Stamps the cost model's current version on the commitment, so the reveal binds to the version live now and rejects a pricingVersion bound to an earlier one with @custom:reverts PricingVersionMismatch. Emits @custom:emits NameCommitted on success.

function commit(bytes32 commitment) external override;

_currentPricingVersion

Reads the cost model's current version through the protocol registry.

Resolved at commit time so the stamp binds the version live then, not at reveal.

function _currentPricingVersion() internal view returns (uint256 pricingVersion);

Returns

NameTypeDescription
pricingVersionuint256The current cost-model version.

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 protocol fee pot via depositProtocolFee 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
    view
    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;