IDotnsPopController

Git Source

Inherits: IDotnsController

Title: IDotnsPopController

Interface for the dedicated PoP controller orchestrating lite-person and full-person username issuance on behalf of the PoP gateway pallet.

Deliberately disjoint from @custom:contract IDotnsRegistrarController. The two controllers coexist on @custom:contract DotnsRegistrar via its multi-controller affordance and neither imports the other. Collision handling reduces to the registrar's ERC721 availability check (first-to-mint wins). Reservation queuing for reservedBaseLabel is an intra-PoP coordination mechanism only; it does not block public registrations. Label formats: Lite-person usernames (first argument to @custom:function reserveBaseName and the liteLabel of a LinkKind.LiteUsername link) are DNS labels with exactly two trailing digits (e.g. alice42) per @custom:function StringUtils.isLitePersonLabel. The gateway strips any separator before calling so the on-chain label is flat. Full-person usernames (the label of @custom:function registerBaseName and the optional reservedBaseLabel of @custom:function reserveBaseName) follow the DNS-label rules enforced by @custom:function StringUtils.isSingleLabel (e.g. alice). Lite and public registrations share one namespace; first-to-mint wins at the ERC721 layer. Cross-flow priority on the stripped base stem is arbitrated by

Notes:

  • function: IPopRules.reserveBaseNameForPop.

  • security-contact: admin@parity.io

Functions

reserveBaseName

Registers a lite-person username on behalf of the supplied user and optionally enqueues a reservation for a base name they intend to claim as a full person later.

Callable only via the registered PoP gateway (otherwise @custom:reverts NotGateway); the gateway is responsible for asserting substrate Root authority before forwarding here. The lite leg validates the dotted stem.NN shape and requires the flattened label to classify as PopLite (otherwise @custom:reverts InvalidLiteLabel), and rejects a supplied chat key whose length is neither zero nor CHAT_KEY_LENGTH (otherwise @custom:reverts InvalidChatKey). On a warm-path mint (user already has a LabelStore) it emits @custom:emits LiteNameReserved and @custom:emits NameRegistered; on a cold-path mint it emits @custom:emits LiteNameReserved and

Notes:

  • emits: PendingClaimStashed, with @custom:emits NameRegistered deferred to

  • function: claimLabelStore when the user settles. The base-name leg only runs when reservedBaseLabel is non-empty: it validates the DNS-label shape and requires a true base label with no trailing digits (otherwise @custom:reverts InvalidBaseLabel) before any queue mutation so a bad reservation never touches the queue, advances the head past expired entries (emitting @custom:emits ReservationExpired for each one), removes the user from any prior queue position so a single user holds at most one live reservation across all labels, and enqueues a fresh entry (emitting

  • emits: ReservationQueued). The enqueue rejects with @custom:reverts AlreadyReserved when the user already holds a reservation that was not cleared by the prior removal and with @custom:reverts QueueFull when the per-label queue has reached MAX_RESERVATION_QUEUE. Cross-chain callers pass the ABI-encoded reservation tuple as the call's payload, which Solidity decodes directly.

function reserveBaseName(BaseReservation calldata params) external;

Parameters

NameTypeDescription
paramsBaseReservationReservation request; see @custom:struct BaseReservation.

reserveBaseName

Raw-payload variant of @custom:function reserveBaseName for cross-chain dispatch.

payload is abi.encode(BaseReservation({...})), the bare ABI-encoded struct with NO function-selector prefix and NO leading bytes-length word. The contract prepends the typed selector and delegatecalls itself so the typed entrypoint runs in the original call context and remains the single source of truth, which means the typed overload's full revert surface bubbles up byte-for-byte: gateway-only access (otherwise @custom:reverts NotGateway), lite-label shape (otherwise

Notes:

  • reverts: InvalidLiteLabel), base-label shape (otherwise

  • reverts: InvalidBaseLabel), duplicate-reservation guard (otherwise

  • reverts: AlreadyReserved), and queue capacity (otherwise

  • reverts: QueueFull). The success path likewise emits the same events as the typed call: @custom:emits LiteNameReserved and @custom:emits NameRegistered on the lite leg, plus @custom:emits ReservationQueued and any @custom:emits ReservationExpired observed while advancing the queue head when the base-name leg runs. Note: abi.decode ignores trailing bytes past the encoded struct, so off-chain encoders MUST NOT assume strict length validation.

function reserveBaseName(bytes calldata payload) external;

Parameters

NameTypeDescription
payloadbytesabi.encode(BaseReservation) produced by the cross-chain caller.

reserveBaseNameOnly

Enqueues only the full/base-name reservation for a user.

Callable only via the registered PoP gateway. This is the second step of the split gateway flow: @custom:function reserveLiteName mints the lite username first, then this function reserves the full/base label in a separate transaction so proof-size stays below per-call limits. Reverts with @custom:reverts InvalidBaseLabel when the label is empty, non-canonical, digit-suffixed, or governance-reserved. The caller remains agnostic about backend batching; it simply exposes a small retryable primitive.

function reserveBaseNameOnly(BaseNameReservation calldata params) external;

Parameters

NameTypeDescription
paramsBaseNameReservationReservation request; see @custom:struct BaseNameReservation.

reserveBaseNameOnly

Raw-payload variant of @custom:function reserveBaseNameOnly for cross-chain dispatch. @param payload abi.encode(BaseNameReservation) produced by the cross-chain caller.

function reserveBaseNameOnly(bytes calldata payload) external;

reserveLiteName

Registers a lite-person username on behalf of the supplied user without touching the base-name reservation queue.

Callable only via the registered PoP gateway (otherwise @custom:reverts NotGateway); the gateway is responsible for asserting substrate Root authority before forwarding here. The supplied label must satisfy the dotted stem.NN shape and the flattened label must classify as PopLite (otherwise @custom:reverts InvalidLiteLabel); a supplied chat key whose length is neither zero nor CHAT_KEY_LENGTH reverts

Notes:

  • reverts: InvalidChatKey before mint and resolver writes run. On a warm-path mint emits @custom:emits LiteNameReserved and @custom:emits NameRegistered. On a cold-path mint emits @custom:emits LiteNameReserved and @custom:emits PendingClaimStashed, with

  • emits: NameRegistered deferred to @custom:function claimLabelStore when the user settles. Cross-chain callers pass the ABI-encoded lite-registration tuple as the call's payload, which Solidity decodes directly.

function reserveLiteName(LiteRegistration calldata params) external;

Parameters

NameTypeDescription
paramsLiteRegistrationRegistration request; see @custom:struct LiteRegistration.

reserveLiteName

Raw-payload variant of @custom:function reserveLiteName for cross-chain dispatch.

payload is abi.encode(LiteRegistration({...})), the bare ABI-encoded struct with NO function-selector prefix and NO leading bytes-length word. The contract prepends the typed selector and delegatecalls itself so the typed entrypoint runs in the original call context and remains the single source of truth, so the typed overload's revert surface bubbles up byte-for-byte: gateway-only access (otherwise

Notes:

  • reverts: NotGateway) and lite-label shape (otherwise

  • reverts: InvalidLiteLabel). The success path emits the same events as the typed call: @custom:emits LiteNameReserved and @custom:emits NameRegistered. Note: abi.decode ignores trailing bytes past the encoded struct, so off-chain encoders MUST NOT assume strict length validation; pad-only junk past the tail is silently dropped (no state corruption; decoded values are unchanged). Worked example off-chain: bytes payload = abi.encode(LiteRegistration({liteLabel: "alice42", user: u, chatKey: k}));

function reserveLiteName(bytes calldata payload) external;

Parameters

NameTypeDescription
payloadbytesabi.encode(LiteRegistration) produced by the cross-chain caller.

registerBaseName

Registers a full-person username on behalf of the supplied user.

Callable only via the registered PoP gateway (otherwise @custom:reverts NotGateway); the gateway is responsible for asserting substrate Root authority before forwarding here. The base label must satisfy the DNS-label shape and be a true base label with no trailing digits (otherwise @custom:reverts InvalidBaseLabel), and the label must not classify as governance-reserved (otherwise @custom:reverts InvalidBaseLabel). The gateway also defers to PopRules as the single cross-flow authority: when PopRules carries a live base-name slot held by another user (stamped by the public commit-reveal flow or this controller's prior queue head), the call reverts @custom:reverts NotHolder before any queue mutation. Two orthogonal axes drive the state machine. The reservation axis treats the user as claiming if and only if they hold the live head-of-queue reservation on the base label: a claim wipes the entire queue, releases the PopRules slot, and emits @custom:emits BaseNameClaimed; a non-claim silently relinquishes any pending entry the user holds and emits @custom:emits StandaloneNameRegistered. Advancing the queue head past expired entries emits @custom:emits ReservationExpired for each one. The chat-key axis selects whether a fresh key is persisted on the resolver or the new entry inherits its key from a prior lite-person username. The fresh-key branch rejects a chat key whose length is neither zero nor CHAT_KEY_LENGTH (otherwise

Notes:

  • reverts: InvalidChatKey). The LiteUsername branch validates the lite label's NAMEXX shape (otherwise @custom:reverts InvalidLiteLabel), requires the registrant to own the lite token (otherwise @custom:reverts LiteLabelNotOwnedByUser), reads the lite node's chat key from the resolver and copies it across; if the lite node carries no chat key the inherited value is empty and the full node's chat-key write is silently skipped (the LiteToFullLinked event still fires). Emits @custom:emits LiteToFullLinked alongside the registration event. On a warm-path mint the event order is

  • emits: NameRegistered first (from the inner mint), then

  • emits: BaseNameClaimed or @custom:emits StandaloneNameRegistered, then

  • emits: LiteToFullLinked when applicable. On a cold-path mint

  • emits: PendingClaimStashed replaces the initial @custom:emits NameRegistered; the deferred @custom:emits NameRegistered fires later from @custom:function claimLabelStore. Cross-chain callers pass the ABI-encoded full-registration tuple as the call's payload, which Solidity decodes directly.

function registerBaseName(FullRegistration calldata params) external;

Parameters

NameTypeDescription
paramsFullRegistrationRegistration request; see @custom:struct FullRegistration.

registerBaseName

Raw-payload variant of @custom:function registerBaseName for cross-chain dispatch.

payload is abi.encode(FullRegistration({...})), the bare ABI-encoded struct with NO function-selector prefix and NO leading bytes-length word. The contract prepends the typed selector and delegatecalls itself so the typed entrypoint runs in the original call context and remains the single source of truth, so the typed overload's revert surface bubbles up byte-for-byte: gateway-only access (otherwise

Note: reverts: NotGateway), base-label shape (otherwise @custom:reverts InvalidBaseLabel), lite-label shape on the LiteUsername branch (otherwise @custom:reverts InvalidLiteLabel), and the standalone-mint holder guard (otherwise @custom:reverts NotHolder). The success path emits the same events as the typed call: @custom:emits BaseNameClaimed on a claim or @custom:emits StandaloneNameRegistered otherwise, @custom:emits LiteToFullLinked on the LiteUsername branch, @custom:emits ReservationExpired for each entry reaped while advancing the queue head, and always @custom:emits NameRegistered. Note: abi.decode ignores trailing bytes past the encoded struct, so off-chain encoders MUST NOT assume strict length validation.

function registerBaseName(bytes calldata payload) external;

Parameters

NameTypeDescription
payloadbytesabi.encode(FullRegistration) produced by the cross-chain caller.

expireReservation

Permissionlessly removes expired entries from the head of a reservation queue.

Permissionless on purpose: anyone (typically a UI or a bot) can poke a stale queue so the next live head takes over without waiting for the next gateway call. Validates the DNS-label shape of reservedBaseLabel (otherwise @custom:reverts InvalidBaseLabel) and emits @custom:emits ReservationExpired for every expired entry reaped from the head. Only base-shaped labels (no trailing digits) ever key a reservation queue, so a lite-shaped label still passes the shape check but resolves to an empty queue and the call is a no-op.

function expireReservation(string calldata reservedBaseLabel) external;

relinquishReservation

Lets the caller voluntarily drop their own active reservation.

Reverts with @custom:reverts NoActiveReservation when the caller holds no live reservation. On success the caller's entry is removed from its queue and

Note: emits: ReservationRelinquished is emitted; if the removed entry was the queue head, head advancement may additionally emit @custom:emits ReservationExpired for any stale entries reaped behind it.

function relinquishReservation() external;

isReservedForClaim

Returns whether a label currently has a live reservation at the queue head.

Validates the DNS-label shape of reservedBaseLabel (otherwise

Note: reverts: InvalidBaseLabel) before inspecting the queue.

function isReservedForClaim(string calldata reservedBaseLabel)
    external
    view
    returns (bool reserved, address holder);

setReservationDuration

Updates the reservation duration used to decide when queue entries expire.

Owner-gated (otherwise @custom:reverts OwnableUnauthorizedAccount); emits

Note: emits: ReservationDurationSet on success.

function setReservationDuration(uint64 duration) external;

reservationMeta

Returns the queue metadata (head, tail) for labelhash.

Read-only accessor over the per-label reservation queue. head == tail means the queue is empty; active entries occupy [head, tail). Exposed on the interface because invariant tests and off-chain consumers (dotli, dweb) use it to enumerate live queue state without scanning storage.

function reservationMeta(bytes32 labelhash) external view returns (uint64 head, uint64 tail);

Parameters

NameTypeDescription
labelhashbytes32Keccak-256 of the base label whose queue is being read.

Returns

NameTypeDescription
headuint64Index of the live queue head.
tailuint64Index one past the last queued entry.

reservationEntry

Returns the queue entry at index for labelhash.

Sparse storage: a zero entryOwner means the slot was relinquished, expired and reaped, or never written. Callers pair this with @custom:function reservationMeta to walk the live window [head, tail).

function reservationEntry(
    bytes32 labelhash,
    uint64 index
)
    external
    view
    returns (address entryOwner, uint64 joinedAt);

Parameters

NameTypeDescription
labelhashbytes32Keccak-256 of the base label whose queue is being read.
indexuint64Queue index to look up.

Returns

NameTypeDescription
entryOwneraddressOwner of the slot (zero if empty/relinquished).
joinedAtuint64Timestamp the entry was enqueued (only meaningful when entryOwner != address(0)).

userReservation

Returns user's current reservation pointer.

A zero labelhash on the returned struct means the user holds no reservation; index is meaningful only when labelhash is non-zero.

function userReservation(address user)
    external
    view
    returns (UserReservation memory reservation);

Parameters

NameTypeDescription
useraddressAccount whose reservation pointer is being read.

Returns

NameTypeDescription
reservationUserReservationPer-user reservation pointer; see @custom:struct UserReservation.

claimLabelStore

Settles the caller's deferred bindings by writing every stashed label into the caller's LabelStore, deploying the store first if the caller doesn't yet have one.

User-signed entrypoint: pallet-revive charges any LabelStore storage deposit against msg.sender's balance through the runtime's configured deposit backend. This is the only path that can create the store, because the Root gateway origin cannot instantiate contracts. Reverts with @custom:reverts NoPendingClaim when the caller holds no live stashed entries. Reuses any existing LabelStore returned by the factory (settling via this controller after a concurrent public-flow mint, or settling twice through this controller, both find a live store and skip deployment), otherwise deploys a fresh store via the protocol-registered factory. Writes each live label keyed by its node (namehash), clears the pending-claim entries, and emits

Note: emits: PendingClaimSettled and @custom:emits NameRegistered per settled name. Chat-key and lite-link records are not touched here; they are persisted on the PoP resolver at mint time, not at settlement.

function claimLabelStore() external;

claimLabelStoreFor

Gateway-driven variant of @custom:function claimLabelStore for split workflows.

Callable only via the registered PoP gateway. It settles the pending LabelStore claim for user without requiring a user transaction. The user-signed

Note: function: claimLabelStore remains as a permissioned-by-origin fallback if gateway dispatch fails.

function claimLabelStoreFor(address user) external;

Parameters

NameTypeDescription
useraddressAccount whose pending claim should be settled.

expirePendingClaim

Permissionlessly reaps a user's deferred bindings that sat unsettled past reservationDuration.

Permissionless on purpose: anyone (typically a UI or a bot) can poke stale entries so the user's pile cannot grow without bound. Sweeps every expired entry, leaving any still-live ones in place; the user is removed from the enumeration set only when no entries remain. Reverts with @custom:reverts NoPendingClaim when the user holds no entries and with @custom:reverts PendingClaimNotExpired when none of the held entries have lapsed. Emits @custom:emits PendingClaimExpired per swept name.

function expirePendingClaim(address user) external;

Parameters

NameTypeDescription
useraddressAddress whose pending claims are being swept.

pendingClaims

Returns user's pending-claim entries.

An empty array means the user has no pending claims. A user accumulates one entry per deferred name until a signed-origin @custom:function claimLabelStore settles them.

function pendingClaims(address user) external view returns (PendingClaim[] memory claims);

Parameters

NameTypeDescription
useraddressAccount whose pending claims are being read.

Returns

NameTypeDescription
claimsPendingClaim[]Per-user pending-claim entries; see @custom:struct PendingClaim.

pendingClaimUserCount

Returns the number of users with at least one live pending claim.

Exact live count, not an all-time tally: fully settled and fully expired users are removed from the enumeration set so off-chain consumers can page through every stalled user without filtering.

function pendingClaimUserCount() external view returns (uint256 count);

Returns

NameTypeDescription
countuint256Number of users currently holding a pending claim.

pendingClaimUsers

Returns a paginated slice of users with at least one live pending claim.

Pair with @custom:function pendingClaims to read each user's stashed entries. Ordering is not chronological; callers MUST NOT assume mintedAt is monotonic across the slice. Returns an empty array when offset is past the live count.

function pendingClaimUsers(
    uint256 offset,
    uint256 limit
)
    external
    view
    returns (address[] memory users);

Parameters

NameTypeDescription
offsetuint256Start index.
limituint256Maximum entries to return.

Returns

NameTypeDescription
usersaddress[]Slice of users currently holding a pending claim.

Events

LiteNameReserved

Emitted when a lite-person username is registered via the PoP gateway.

event LiteNameReserved(bytes32 indexed labelhash, address indexed user, string label);

BaseNameClaimed

Emitted when a full-person username is claimed out of an existing reservation.

event BaseNameClaimed(bytes32 indexed labelhash, address indexed user, string label);

StandaloneNameRegistered

Emitted when a standalone full-person username is registered via the PoP gateway.

event StandaloneNameRegistered(bytes32 indexed labelhash, address indexed user, string label);

ReservationQueued

Emitted when a reservation entry is added to the queue for a base name.

event ReservationQueued(
    bytes32 indexed reservedLabelhash, address indexed user, uint64 position
);

Parameters

NameTypeDescription
reservedLabelhashbytes32
useraddress
positionuint64Position in the queue at the time of joining (0 = active holder).

ReservationExpired

Emitted when a reservation entry is removed due to expiry.

event ReservationExpired(bytes32 indexed reservedLabelhash, address indexed user);

ReservationRelinquished

Emitted when a user voluntarily relinquishes their reservation.

event ReservationRelinquished(bytes32 indexed reservedLabelhash, address indexed user);

LiteToFullLinked

Emitted when a full-person username is linked to a lite-person username.

event LiteToFullLinked(bytes32 indexed fullLabelhash, bytes32 indexed liteLabelhash);

ReservationDurationSet

Emitted when the reservation duration is updated.

event ReservationDurationSet(uint64 duration);

NameRegistered

Emitted when a name is successfully registered via the PoP controller.

event NameRegistered(
    string indexed label, bytes32 indexed labelhash, address indexed owner, address store
);

Parameters

NameTypeDescription
labelstring
labelhashbytes32
owneraddress
storeaddressThe Store instance used to persist the immutable registration record.

PendingClaimStashed

Emitted when a gateway-path mint defers its LabelStore write into the pending-claim mapping because the user has no store yet.

event PendingClaimStashed(address indexed user, bytes32 indexed labelhash, string label);

PendingClaimSettled

Emitted when a user settles a deferred binding by deploying their LabelStore and backfilling the stashed label and chat key.

event PendingClaimSettled(address indexed user, bytes32 indexed labelhash, address store);

PendingClaimExpired

Emitted when a deferred binding is reaped because it sat unsettled past reservationDuration.

event PendingClaimExpired(address indexed user, bytes32 indexed labelhash);

ReservationHeadAdvanced

Emitted when a reservation queue's head transitions to a new user, either via expiry of the prior head or via the explicit relinquish path.

event ReservationHeadAdvanced(bytes32 indexed labelhash, address indexed newHead);

Parameters

NameTypeDescription
labelhashbytes32Base-label hash whose queue head changed.
newHeadaddressAddress now holding the head slot.

Errors

NotGateway

Thrown when a gated entrypoint is reached from an address that is not the gateway registered on the protocol registry under the PoP gateway key.

The controller delegates substrate Root-authority verification to the registered gateway, which is the Root gateway dispatcher, and authorises calls solely against the address resolved from the protocol registry. The caller parameter carries the immediate EVM caller observed by this contract for off-chain diagnostics.

error NotGateway(address caller);

Parameters

NameTypeDescription
calleraddressImmediate EVM caller observed by this contract.

InvalidLiteLabel

Thrown when a supplied lite-person label does not match NAMEXX.

error InvalidLiteLabel();

InvalidBaseLabel

Thrown when a supplied base label is not a canonical DNS label.

error InvalidBaseLabel();

InvalidChatKey

Thrown when a supplied chat key is non-empty and not exactly 65 bytes long.

Mirrors the resolver's InvalidChatKeyLength so the controller surfaces a controller-local error before the mint runs.

error InvalidChatKey(uint256 length);

Parameters

NameTypeDescription
lengthuint256Caller-supplied chat key length, in bytes.

NoActiveReservation

Thrown when a user tries to claim or relinquish a reservation that they do not hold.

error NoActiveReservation(address user);

QueueFull

Thrown when a reservation queue has reached its capacity.

error QueueFull(bytes32 labelhash);

AlreadyReserved

Thrown when attempting to enqueue a user who already has an active reservation.

error AlreadyReserved(address user, bytes32 labelhash);

NotHolder

Thrown when someone tries to mint a base label in standalone mode while another user holds the live head-of-queue reservation.

error NotHolder(address user, bytes32 labelhash);

NoPendingClaim

Thrown when @custom:function claimLabelStore is called by a user with no recorded pending-claim entries.

error NoPendingClaim(address user);

Parameters

NameTypeDescription
useraddressCaller observed by the controller.

PendingClaimNotExpired

Thrown when @custom:function expirePendingClaim is invoked but the user holds no entry past its mintedAt + reservationDuration deadline.

error PendingClaimNotExpired(address user);

Parameters

NameTypeDescription
useraddressAddress whose entries are being inspected.

LiteLabelNotOwnedByUser

Thrown when a lite-link inheritance does not match the registrar-side owner of the lite label.

Prevents identity hijack by ensuring the registrant on the full-name leg actually holds the prior lite identity whose chat key is being inherited.

error LiteLabelNotOwnedByUser(address user, bytes32 liteLabelhash);

Parameters

NameTypeDescription
useraddressRegistrant supplied by the gateway.
liteLabelhashbytes32Lite label whose ownership did not match.

ReservationDurationTooLow

Thrown when @custom:function setReservationDuration is called with a value below the protocol minimum.

error ReservationDurationTooLow(uint64 duration);

Parameters

NameTypeDescription
durationuint64Caller-supplied duration, in seconds.

Structs

Tagged union selecting the chat-key source for a full-person registration.

struct Link {
    LinkKind kind;
    string liteLabel;
    bytes chatKey;
}

Properties

NameTypeDescription
kindLinkKind
liteLabelstringLite-person NAMEXX label (only read when kind == LiteUsername).
chatKeybytesChat key bytes (only read when kind == None).

UserReservation

Per-user reservation pointer: which queue the user sits in and where.

struct UserReservation {
    bytes32 labelhash;
    uint64 index;
}

Properties

NameTypeDescription
labelhashbytes32Non-zero when the user holds a live reservation; zero otherwise.
indexuint64Monotonic queue index, meaningful only when labelhash is non-zero.

ReservationEntry

Reservation queue entry: a user and the timestamp they joined the queue.

Packs into a single storage slot (20 + 8 bytes).

struct ReservationEntry {
    address owner;
    uint64 joinedAt;
}

ReservationQueueMeta

Metadata describing the occupied range of a reservation queue.

Uses monotonically increasing indices. Active entries occupy [head, tail); length = tail - head. Slots past head are deleted as the head advances so garbage never accumulates.

struct ReservationQueueMeta {
    uint64 head;
    uint64 tail;
}

PendingClaim

Deferred per-user binding of a freshly minted name to its LabelStore.

Recorded by the gateway path when the user has no LabelStore. The user later settles the binding via @custom:function claimLabelStore, which deploys the store from a signed origin and writes the stashed label. PoP-resolver records (chat key, lite link) are persisted eagerly at mint time on

Note: contract: IDotnsPopResolver, not at settlement, so the resolver carries the full identity record regardless of whether the user has settled their Store. A user accumulates one entry per deferred name: the Root gateway path cannot deploy a LabelStore (contract creation is forbidden from the Root origin), so it keeps stashing entries until a signed-origin @custom:function claimLabelStore deploys the store and settles every entry at once. Each entry's expiry is measured from its own mintedAt against reservationDuration.

struct PendingClaim {
    string label;
    uint64 mintedAt;
}

Properties

NameTypeDescription
labelstringBare DNS label (no TLD); the TLD is appended at settlement time.
mintedAtuint64Timestamp of the originating mint.

LiteRegistration

Lite-person registration payload.

Single struct so the gateway can ABI-encode one tuple as the cross-chain payload and the contract decodes it directly out of msg.data. All fields are required; chatKey may be empty bytes to skip the resolver write.

struct LiteRegistration {
    string liteLabel;
    address user;
    bytes chatKey;
}

Properties

NameTypeDescription
liteLabelstringLite-person NAMEXX label being minted.
useraddressBeneficiary account on this chain.
chatKeybytesChat-key bytes persisted on the PoP resolver. Empty leaves the slot unset.

BaseReservation

Lite-person registration combined with an optional base-name reservation.

BaseReservation is a @custom:struct LiteRegistration plus a base-label reservation slot, expressed as composition rather than duplicated fields so internal helpers can consume the lite leg via params.lite without unpacking. The lite leg always runs; the reservation leg only runs when reservedBaseLabel is non-empty.

struct BaseReservation {
    LiteRegistration lite;
    string reservedBaseLabel;
}

Properties

NameTypeDescription
liteLiteRegistrationLite-person registration request; see LiteRegistration.
reservedBaseLabelstringBase label to enqueue for a later full-person claim. Empty string skips the reservation leg.

BaseNameReservation

Base-name reservation payload for the split gateway flow.

This is the reservation-only primitive. The lite username mint is handled by

Notes:

  • function: reserveLiteName, and LabelStore settlement is handled by

  • function: claimLabelStoreFor or the user fallback @custom:function claimLabelStore.

struct BaseNameReservation {
    address user;
    string reservedBaseLabel;
}

Properties

NameTypeDescription
useraddressBeneficiary account that will hold the reservation.
reservedBaseLabelstringBase label to enqueue for a later full-person claim.

FullRegistration

Full-person registration payload.

struct FullRegistration {
    string label;
    address user;
    Link link;
}

Properties

NameTypeDescription
labelstringBase DNS label being minted.
useraddressBeneficiary account on this chain.
linkLinkChat-key source for the new entry; see @custom:struct Link.

Enums

LinkKind

Discriminant for the Link union supplied to registerBaseName.

Selects the chat-key source for the full-person username. Orthogonal to whether the registration is a claim or standalone; that is derived from on-chain reservation state. None means the caller supplies a fresh chat key in link.chatKey. LiteUsername means the full-person username is linked to a prior lite-person username (link.liteLabel) and inherits its chat key.

enum LinkKind {
    None,
    LiteUsername
}