DotnsRegistrarController
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;
maxAgemust exceedminAge(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
| Name | Type | Description |
|---|---|---|
pricingVersion | uint256 | The 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
| Name | Type | Description |
|---|---|---|
versionString | string | Current 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;