DotnsNameWhitelist
Inherits: Initializable, UUPSUpgradeable, OwnableUpgradeable, ERC165Upgradeable, IDotnsNameWhitelist
Title: DotnsNameWhitelist
Pre-launch name whitelist. A name is Open until governance reserves it or a claim is
accepted for it. Several beneficiaries may claim the same Open name, each with a
reason, and governance accepts one as the winner. A grant binds its name for
grantDuration; once that passes, the name reads Open again.
Lives behind its own UUPS proxy with its own storage. Callers pass bare labels only; the
contract derives the node from the label and the TLD in the protocol registry, so a
caller cannot supply a mismatched hash. Claims are keyed by the beneficiary user, not
the submitter, so a relayer or a cross-chain sovereign account can submit on a user's
behalf and the name binds to that user. All state is on-chain and queryable through views;
no event indexing is required. A name holds at most maxClaimants live claims, which
bounds the loop that clears them on resolution. Resolving a name deletes its claims,
refunding their storage deposit, so only reserved or won names persist. The entire admin
surface is substrate Root: SystemUtils.originIsRoot is true through the proxy's
delegatecall frame, and no gate reads msg.sender, so Root's lack of an address is not a
problem. No signed account grants, revokes, reserves, or retunes a cap; the owner's
authority is upgrade only. The public and PoP controllers hold only the consume hook.
Entries are keyed by the node under the active TLD, which the deployment holds immutable
for the whitelist's lifetime.
Note: security-contact: admin@parity.io
State Variables
protocolRegistry
Protocol-level address registry for all dotNS contracts.
IDotnsProtocolRegistry public protocolRegistry
maxClaimants
Live-claim cap per name, tunable by governance within
DotnsConstants.WHITELIST_MAX_CLAIMANTS_LIMIT.
uint16 public maxClaimants
maxGrantBatch
Cap on labels per grantNames call, tunable by governance within
DotnsConstants.WHITELIST_MAX_GRANT_BATCH_LIMIT.
uint16 public maxGrantBatch
maxReasonBytes
Reason byte cap, tunable by governance within
DotnsConstants.WHITELIST_MAX_REASON_LIMIT.
uint256 public maxReasonBytes
_names
Resolved state per name.
mapping(bytes32 node => NameRecord record) private _names
_claims
Claims per name, keyed by beneficiary.
mapping(bytes32 node => mapping(address user => Claim claim)) private _claims
_claimants
Beneficiaries with a live claim per name.
mapping(bytes32 node => EnumerableSet.AddressSet claimants) private _claimants
_activeNodes
Names holding reserved, claimed or claim-holding state, kept enumerable for review.
EnumerableSet.Bytes32Set private _activeNodes
_requestOpen
Timestamp requests start being accepted.
uint64 private _requestOpen
_requestClose
Timestamp requests stop being accepted.
uint64 private _requestClose
grantDuration
Period a grant binds its name, tunable by governance within
DotnsConstants.WHITELIST_MIN_GRANT_DURATION and
DotnsConstants.WHITELIST_MAX_GRANT_DURATION.
uint64 public grantDuration
_grantClockStart
Earliest timestamp a grant period runs from.
Set when grant expiry is initialised. A grant recorded before then has no grantedAt,
so its period runs from here.
uint64 private _grantClockStart
__gap
Reserved storage space to allow for layout changes in the future.
uint256[50] private __gap
Functions
onlyGovernance
Restricts a call to a substrate Root dispatch.
The whole admin surface is governance-only: no key grants, revokes, reserves, or
retunes a cap. The owner's authority is deployment and upgrade, not allocation, so no
signed account can hand out a name. msg.sender is never read here, which is also what
keeps every gated entry point callable under a Root origin, since Root has no account.
modifier onlyGovernance() ;
onlyController
Restricts a call to a registrar controller resolved through the registry.
modifier onlyController() ;
_onlyGovernance
Internal check enforcing the substrate Root gate.
function _onlyGovernance() internal view;
constructor
Note: oz-upgrades-unsafe-allow: constructor
constructor() ;
initialize
Initialises the whitelist.
Callable once through the UUPS proxy; direct calls on the implementation
Note:
reverts: InvalidInitialization. Sets initialOwner as owner and wires the
protocol registry the node derivation reads the TLD from.
function initialize(
address initialOwner,
IDotnsProtocolRegistry registry
)
external
initializer;
Parameters
| Name | Type | Description |
|---|---|---|
initialOwner | address | Address that owns the contract once initialised. |
registry | IDotnsProtocolRegistry | Protocol registry all dotNS contracts resolve through. |
initializeGrantExpiry
Starts grant expiry on a whitelist initialised without it.
Called once by the owner through upgradeToAndCall, so the upgrade and the clock
start land in one call. Starts the clock for grants made before it, which have no
grantedAt, and sets the default grant period unless governance already set one. A
whitelist whose clock already runs @custom:reverts InvalidInitialization.
function initializeGrantExpiry() external reinitializer(2) onlyOwner;
_initializeGrantExpiry
Starts the grant clock, and sets the default grant period when none is set.
function _initializeGrantExpiry() internal;
setMaxClaimants
Sets the live-claim cap per name.
Restricted to a substrate Root dispatch. The cap is bounded by
DotnsConstants.WHITELIST_MAX_CLAIMANTS_LIMIT, which bounds the resolution clear-loop.
Notes:
-
reverts: MaxClaimantsOutOfRange when
newMaxis zero or above the ceiling. -
emits: MaxClaimantsSet.
function setMaxClaimants(uint16 newMax) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
newMax | uint16 | New per-name claim cap. |
setMaxReasonBytes
Sets the reason byte cap.
Restricted to a substrate Root dispatch, bounded by
DotnsConstants.WHITELIST_MAX_REASON_LIMIT. @custom:reverts MaxReasonBytesOutOfRange when
newMax is zero or above the ceiling. @custom:emits MaxReasonBytesSet.
function setMaxReasonBytes(uint256 newMax) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
newMax | uint256 | New reason byte cap. |
setMaxGrantBatch
Sets the cap on labels per grantNames call.
Restricted to a substrate Root dispatch, bounded by
DotnsConstants.WHITELIST_MAX_GRANT_BATCH_LIMIT. @custom:reverts MaxGrantBatchOutOfRange
when newMax is zero or above the ceiling. @custom:emits MaxGrantBatchSet.
function setMaxGrantBatch(uint16 newMax) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
newMax | uint16 | New batch cap. |
setGrantDuration
Sets the period a grant binds its name.
Restricted to a substrate Root dispatch, bounded by
DotnsConstants.WHITELIST_MIN_GRANT_DURATION and
DotnsConstants.WHITELIST_MAX_GRANT_DURATION. Expiry is computed on read, so the new
period applies to every live grant: lengthening it extends them and shortening it can
expire them at once. @custom:reverts GrantDurationOutOfRange when newDuration is out of
range. @custom:emits GrantDurationSet.
function setGrantDuration(uint64 newDuration) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
newDuration | uint64 | New grant period, in seconds. |
requestName
Claims label for user.
Permissionless within the window; the submitter may differ from user. Requires the
name Open, the window open, user non-zero, a canonical label, user without an
existing claim, and fewer than maxClaimants claims on the name.
Notes:
-
reverts: WindowClosed, @custom:reverts NameNotOpen, @custom:reverts ZeroUser,
-
emits: NameRequested.
function requestName(
string calldata label,
string calldata reason,
address user
)
external
override;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to claim. |
reason | string | Free-text justification, at most maxReasonBytes bytes. |
user | address | Beneficiary the name binds to if this claim wins. |
accept
Accepts user's claim as the winner of label.
Restricted to a substrate Root dispatch. Requires user's claim Requested.
Sets the name Claimed with user the winner and clears every claim on the name, rejecting
the losers. @custom:reverts NotRequested. @custom:emits NameAccepted for the winner and
Note: emits: NameRejected for each loser.
function accept(string calldata label, address user) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to resolve. |
user | address | Beneficiary whose claim wins. |
reject
Rejects user's pending claim on label without resolving the name.
Restricted to a substrate Root dispatch. Requires the claim Requested.
Note: reverts: NotRequested. @custom:emits NameRejected.
function reject(string calldata label, address user) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label. |
user | address | Beneficiary whose claim is rejected. |
grantName
Grants label to user directly, without a prior claim.
Restricted to a substrate Root dispatch. Requires the name Open, which an expired
grant is, user non-zero and a canonical label. Sets the name Claimed with user the
winner, starts the grant period, and clears any pending
claims. @custom:reverts NameNotOpen, @custom:reverts ZeroUser or
Notes:
-
reverts: InvalidLabel. @custom:emits NameAccepted, and
-
emits: NameRejected for each cleared claim.
function grantName(string calldata label, address user) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to grant. |
user | address | Beneficiary the name binds to. |
grantNames
Grants several labels to one user directly.
Restricted to a substrate Root dispatch. Applies @custom:function grantName to
each, at most maxGrantBatch labels per call.
Note:
reverts: TooManyLabels when labels exceeds the batch cap.
function grantNames(string[] calldata labels, address user) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
labels | string[] | Bare labels to grant. |
user | address | Beneficiary each name binds to. |
revokeName
Resets label to Open, clearing any winner and claims.
Restricted to a substrate Root dispatch. Resolves a Claimed or claim-holding name, an expired grant included, so governance can tidy a lapsed entry from the active set; a Reserved name is released through @custom:function setReserved, not here.
Notes:
-
reverts: NothingToRevoke when the name is not Claimed and holds no claims.
-
emits: NameRevoked, and @custom:emits NameRejected for each cleared claim.
function revokeName(string calldata label) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to reset. |
setReserved
Reserves or releases label.
Restricted to a substrate Root dispatch. Reserving requires the name Open and clears
any pending claims, rejecting each; releasing requires it Reserved. @custom:reverts
NameNotOpen or @custom:reverts NotReserved. @custom:emits NameReserved or @custom:emits
NameUnreserved. @param label Bare label.
function setReserved(string calldata label, bool reserved) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | |
reserved | bool | True to reserve, false to release. |
consume
Removes the win on label as registrant registers it.
Restricted to the registrar controllers resolved through the protocol registry. Resets the name to Open. @custom:reverts NotController for any other caller and
Notes:
-
reverts: NotWinner when
labelis not won byregistrantor the grant has expired. -
emits: NameConsumed.
function consume(string calldata label, address registrant) external override onlyController;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label being registered. |
registrant | address | Address registering the name. |
setWindow
Sets the request window relative to the current time.
Restricted to a substrate Root dispatch. Opens at block.timestamp + startsIn for
duration. @custom:reverts BadWindow when duration is zero. @custom:emits WindowSet.
function setWindow(uint64 startsIn, uint64 duration) external override onlyGovernance;
Parameters
| Name | Type | Description |
|---|---|---|
startsIn | uint64 | Seconds from now until requests start being accepted. |
duration | uint64 | Seconds the window stays open. |
statusOf
Returns the status of label.
An expired grant reads Open.
function statusOf(string calldata label) external view override returns (NameStatus status);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
Returns
| Name | Type | Description |
|---|---|---|
status | NameStatus | Name status; see NameStatus. |
isReserved
Returns whether label is reserved.
function isReserved(string calldata label) external view override returns (bool reserved);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
Returns
| Name | Type | Description |
|---|---|---|
reserved | bool | True when the name is Reserved. |
granteeOf
Returns the winner of label, or the zero address when not Claimed.
Zero once the grant expires.
function granteeOf(string calldata label) external view override returns (address winner);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
Returns
| Name | Type | Description |
|---|---|---|
winner | address | Winning beneficiary. |
granteeOfNode
Returns the winner of the name at node, or the zero address when not Claimed.
The check the controllers use to keep every other path off a granted name. They already hold the node, so this skips the TLD lookup @custom:function granteeOf makes, which keeps the gateway's proof smaller. Zero once the grant expires.
function granteeOfNode(bytes32 node) external view override returns (address winner);
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
Returns
| Name | Type | Description |
|---|---|---|
winner | address | Winning beneficiary. |
grantExpiresAt
Returns when the grant on label expires, or zero when the name is not Claimed.
The grant binds the name while block.timestamp is below this value. Reads
type(uint64).max on a whitelist upgraded without initializeGrantExpiry, where
grants do not expire yet.
function grantExpiresAt(string calldata label)
external
view
override
returns (uint64 expiresAt);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
Returns
| Name | Type | Description |
|---|---|---|
expiresAt | uint64 | Timestamp the grant expires at. |
isGrantedTo
Returns whether account won label.
The pair check the controllers use to admit a registrant. False for the zero address and once the grant expires.
function isGrantedTo(
string calldata label,
address account
)
external
view
override
returns (bool granted);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
account | address | Address to test against the winner. |
Returns
| Name | Type | Description |
|---|---|---|
granted | bool | True when account is the winner. |
claimOf
Returns user's claim on label.
function claimOf(
string calldata label,
address user
)
external
view
override
returns (Claim memory claim);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
user | address | Beneficiary to look up. |
Returns
| Name | Type | Description |
|---|---|---|
claim | Claim | The stored claim; a zeroed struct with None status when absent. |
claimantCount
Returns the number of live claims on label.
function claimantCount(string calldata label) external view override returns (uint256 count);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
Returns
| Name | Type | Description |
|---|---|---|
count | uint256 | Live claim count. |
claims
Returns a page of claims on label for review.
Reads the canonical offset and limit window.
function claims(
string calldata label,
uint256 offset,
uint256 limit
)
external
view
override
returns (Claim[] memory page);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to look up. |
offset | uint256 | Index of the first claim. |
limit | uint256 | Maximum number of claims to return. |
Returns
| Name | Type | Description |
|---|---|---|
page | Claim[] | Claims in the window. |
nameCount
Returns the number of names with reserved, claimed or claim-holding state.
function nameCount() external view override returns (uint256 count);
Returns
| Name | Type | Description |
|---|---|---|
count | uint256 | Active name count. |
names
Returns a page of active names for review.
Reads the canonical offset and limit window. Iteration order is not stable. An
expired grant stays in the set until a write on the name clears it, and reads Open
with no winner.
function names(
uint256 offset,
uint256 limit
)
external
view
override
returns (NameView[] memory page);
Parameters
| Name | Type | Description |
|---|---|---|
offset | uint256 | Index of the first name. |
limit | uint256 | Maximum number of names to return. |
Returns
| Name | Type | Description |
|---|---|---|
page | NameView[] | Names in the window. |
window
Returns the request window.
function window() external view override returns (uint64 openAt, uint64 closeAt);
Returns
| Name | Type | Description |
|---|---|---|
openAt | uint64 | Timestamp requests start being accepted. |
closeAt | uint64 | Timestamp requests stop being accepted. |
isWindowOpen
Returns whether requests are currently accepted.
function isWindowOpen() external view override returns (bool open);
Returns
| Name | Type | Description |
|---|---|---|
open | bool | True when the current time is within the window. |
supportsInterface
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC165Upgradeable)
returns (bool supported);
_grant
Grants label to user directly, clearing any pending claims.
function _grant(string calldata label, address user) internal;
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to grant. |
user | address | Beneficiary the name binds to. |
_settle
Marks a name claimed for winner and clears its claims, rejecting the losers.
function _settle(bytes32 node, address winner, string calldata label) internal;
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
winner | address | Beneficiary the name binds to. |
label | string | Bare label, stored for review. |
_granteeOf
Returns the live winner of the name at node, or the zero address.
function _granteeOf(bytes32 node) internal view returns (address winner);
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
Returns
| Name | Type | Description |
|---|---|---|
winner | address | Winning beneficiary while the grant binds. |
_statusOf
Returns the status of record, reading an expired grant as Open.
function _statusOf(NameRecord storage record) internal view returns (NameStatus status);
Parameters
| Name | Type | Description |
|---|---|---|
record | NameRecord | Stored record of the name. |
Returns
| Name | Type | Description |
|---|---|---|
status | NameStatus | Effective name status. |
_expiryOf
Returns when the grant held in record expires.
The period runs from grantedAt, or from the grant clock start for a grant made
before expiry was initialised. The clock is unset only on a whitelist upgraded
without initializeGrantExpiry; every grant then keeps binding, whatever period
governance sets in the meantime, so neither a separate upgrade call nor an early
setGrantDuration can open granted names.
function _expiryOf(NameRecord storage record) internal view returns (uint64 expiresAt);
Parameters
| Name | Type | Description |
|---|---|---|
record | NameRecord | Stored record of a Claimed name. |
Returns
| Name | Type | Description |
|---|---|---|
expiresAt | uint64 | Timestamp the grant expires at; type(uint64).max while the clock is unset. |
_clearExpiredGrant
Resets an expired grant in record to Open and returns the resulting status.
Run by the writes that need an Open name, so a lapsed grant is never carried into a new state.
function _clearExpiredGrant(NameRecord storage record) internal returns (NameStatus status);
Parameters
| Name | Type | Description |
|---|---|---|
record | NameRecord | Stored record of the name. |
Returns
| Name | Type | Description |
|---|---|---|
status | NameStatus | Status of the name after the reset. |
_clearClaimants
Deletes every claim on a name, rejecting each claimant that is not winner.
function _clearClaimants(bytes32 node, address winner, string calldata label) internal;
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
winner | address | Claimant spared a rejection event; the zero address rejects every claimant. |
label | string | Bare label emitted with each rejection. |
_activate
Records a name as active and stores its label the first time it is seen.
function _activate(bytes32 node, string calldata label) internal;
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
label | string | Bare label stored on first activation. |
_deactivate
Drops a name from the active set once it is Open with no claims.
function _deactivate(bytes32 node) internal;
Parameters
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
_nodeOf
Derives the namehash of label under the active TLD read from the registry.
function _nodeOf(string calldata label) internal view returns (bytes32 node);
Parameters
| Name | Type | Description |
|---|---|---|
label | string | Bare label to hash. |
Returns
| Name | Type | Description |
|---|---|---|
node | bytes32 | Namehash of the label under the active TLD. |
_isWindowOpen
Returns whether the current time is within the open window.
function _isWindowOpen() internal view returns (bool open);
Returns
| Name | Type | Description |
|---|---|---|
open | bool | True when the current time is within the window. |
_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;