IDotnsNameEscrow

Git Source

Title: Dotns Name Escrow Interface

Escrows refundable deposits for .dot registrations and manages the release lifecycle.

Note: security-contact: admin@parity.io

Functions

reserves

Returns total amount of assets liabilities reserved for withdrawals.

function reserves(address asset) external view returns (uint256 amount);

Parameters

NameTypeDescription
assetaddressAsset address. address(0) denotes native token.

getReleasePosition

Returns the escrow state for a token.

function getReleasePosition(uint256 tokenId)
    external
    view
    returns (ReleasePosition memory position);

releasedTokenCount

Returns the number of tokens currently held by escrow pending reclaim or withdrawal.

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

Returns

NameTypeDescription
countuint256Number of released tokens not yet reclaimed.

releasedTokens

Returns a bounded paginated slice of released token identifiers.

limit must be non-zero and at most MAX_RELEASED_PAGE_SIZE, otherwise

Note: reverts: InvalidPageSize.

function releasedTokens(
    uint256 start,
    uint256 limit
)
    external
    view
    returns (uint256[] memory tokenIds);

Parameters

NameTypeDescription
startuint256Start index into the released-token set.
limituint256Maximum number of token identifiers to return.

deposit

Records an asset deposit position for a token.

Only the configured controller may call this, otherwise @custom:reverts NotController. params.amount must equal msg.value, otherwise @custom:reverts InvalidAmount; a zero amount is accepted so cross-payer and free-tier registrations can still seed a position that the release lifecycle can advance. Only native deposits are accepted today, so a non-zero params.asset triggers @custom:reverts AssetNotSupported, and a zero params.recipient triggers @custom:reverts InvalidRecipient. The slot for params.tokenId must be empty (sentinel: position.recipient == address(0)): a previously funded position triggers @custom:reverts PositionAlreadyFunded, and a position already in the released phase triggers @custom:reverts AlreadyReleased. Emits @custom:emits NativeDepositRecorded once the deposit is booked.

function deposit(DepositParams calldata params) external payable;

depositInsurance

Records a cross-tier registration fee into the insurance fund.

Only the configured controller may call this, otherwise @custom:reverts NotController. msg.value must be non-zero, otherwise @custom:reverts InvalidAmount. Emits

Note: emits: CrossTierFeePaid with isRegistration = true once the fee is booked.

function depositInsurance(InsuranceDepositParams calldata params) external payable;

creditOverpayment

Credits msg.value to recipient's pull-payment ledger so the caller can later pull the balance with @custom:func claimWithdrawal.

Only the configured controller may call this, otherwise @custom:reverts NotController. recipient must be non-zero (@custom:reverts InvalidRecipient) and msg.value must be non-zero (@custom:reverts InvalidAmount). Used by the registrar controller to refund overpayment without pushing native value into a potentially reverting contract receiver. Emits @custom:emits OverpaymentRefunded once the credit lands.

function creditOverpayment(address recipient) external payable;

Parameters

NameTypeDescription
recipientaddressAddress whose pending balance should grow by msg.value.

chargeTransferFee

Charges transfer friction and rebinds the token's escrow position to the new holder.

Only the configured registrar may call this, otherwise @custom:reverts NotRegistrar. When a fee is owed, the attached value must cover it or @custom:reverts InsufficientValue. Whenever a position exists for the token and the NFT is leaving its prior recipient, the position recipient is rebound to the new holder so the deposit (when funded) and the lifecycle marker (when zero-amount) both follow the NFT. The escrow does not refund anyone at transfer time; the only path back to the locked deposit is for the current holder to release into escrow and wait the cooldown. Emits @custom:emits CrossTierFeePaid (non-registration) when a non-zero fee is credited to insurance, and credits any surplus value to the payer on the time-locked refund ledger via @custom:emits RefundCredited.

function chargeTransferFee(ChargeTransferFeeParams calldata params)
    external
    payable
    returns (uint256 charged);

Returns

NameTypeDescription
chargeduint256Amount actually credited to insurance.

insuranceFund

Returns the cumulative cross-tier fee balance held against future shortfalls.

function insuranceFund() external view returns (uint256 balance);

Returns

NameTypeDescription
balanceuint256Current insurance fund balance, in wei.

release

Releases a token into escrow and starts the withdrawal cooldown.

First step of the phased lifecycle. The caller must be the current NFT holder and the current position recipient (the field is rebound to the holder on every transfer that moves the name off the prior recipient), otherwise @custom:reverts NotRefundRecipient. Approved operators cannot release on behalf of the holder because the recipient field is keyed to the holder, not to any approval set, which keeps the deposit refund tied to the on-chain owner. The slot for tokenId must already hold a position (sentinel: position.recipient != address(0)); an unseeded slot triggers @custom:reverts DepositNotConfigured, and a position already in the released phase triggers

Note: reverts: AlreadyReleased. Zero-amount positions are still releasable so every minted name has a reachable lifecycle. The escrow must additionally be approved to move the NFT, otherwise @custom:reverts EscrowNotApproved. Emits @custom:emits NameReleased once the NFT is moved into custody.

function release(uint256 tokenId) external;

withdraw

Credits the refundable deposit for a released token to the recipient's pending balance.

Second step of the phased lifecycle. The position must already be released (@custom:reverts NotReleased otherwise) and not yet claimed (@custom:reverts AlreadyClaimed on re-entry). Only the current position recipient (the address that released the name, which mirrored the NFT holder at that moment) may call this, otherwise @custom:reverts NotRefundRecipient, and block.timestamp must have reached withdrawAvailableAt, otherwise @custom:reverts WithdrawalTooEarly. Draws from the per-asset tokenReserved pool first and falls back to the shared insurance fund on shortfall; if even the combined balance is short, @custom:reverts InsufficientFunds. Funds are not transferred here, only credited to the pull-payment ledger. Emits

Note: emits: RefundWithdrawn once the credit lands, and @custom:emits InsuranceDraw whenever the insurance fund tops up a shortfall.

function withdraw(uint256 tokenId) external;

claimWithdrawal

Pulls the caller's accumulated pending refund balance.

Final step of the phased lifecycle. Pull-payment isolation: each recipient owns an independent ledger entry, so a failing or reentrant receiver cannot block other users' withdrawals. The caller must have a positive pending balance, otherwise

Notes:

  • reverts: NoPendingWithdrawal; a failing native transfer triggers

  • reverts: RefundFailed. Emits @custom:emits WithdrawalClaimed once the transfer succeeds.

function claimWithdrawal() external returns (uint256 amount);

Returns

NameTypeDescription
amountuint256Native amount transferred to the caller.

pendingWithdrawal

Returns the pending refund balance owed to recipient.

function pendingWithdrawal(address recipient) external view returns (uint256 amount);

Returns

NameTypeDescription
amountuint256Native amount currently credited to recipient and pullable via claimWithdrawal.

reclaim

Transfers a released-and-claimed token from escrow custody to a new owner.

Hands the NFT back to the controller for re-registration. Only the configured controller may call this, otherwise @custom:reverts NotController, and the position must be both released and claimed, otherwise @custom:reverts NotReclaimable. Emits

Note: emits: NameReclaimed once custody is transferred.

function reclaim(uint256 tokenId, address newOwner) external;

Parameters

NameTypeDescription
tokenIduint256
newOwneraddressAddress of the new registrant taking over the name.

updateCooldown

Updates the cooldown duration for future releases.

Owner-only. Affects only releases recorded after this call; positions already released keep the withdrawAvailableAt snapshot taken at their release time. newCooldown must be non-zero, otherwise @custom:reverts InvalidCooldown, and must not exceed the contract's MAX_COOLDOWN upper bound, otherwise @custom:reverts CooldownTooLong; the bound keeps the release-to-reclaim window short and protects the uint64 cast in release from truncation. Emits @custom:emits CooldownUpdated with the prior and new values.

function updateCooldown(uint256 newCooldown) external;

claimRefund

Pulls a single time-locked refund entry.

Caller must be the entry's recipient (@custom:reverts NotRefundRecipient otherwise), the entry must exist (@custom:reverts NoSuchRefundEntry on a deleted or unknown id), and block.timestamp must have reached availableAt (@custom:reverts RefundLocked otherwise). The entry is deleted before the transfer; a failing native transfer triggers @custom:reverts RefundFailed. Emits @custom:emits RefundClaimed.

function claimRefund(uint256 entryId) external returns (uint256 amount);

Parameters

NameTypeDescription
entryIduint256Identifier of the entry to claim.

Returns

NameTypeDescription
amountuint256Native amount transferred to the caller.

claimRefundsBatch

Pulls multiple time-locked refund entries in one call.

Atomic: any invalid entry in the batch (wrong recipient, missing, or locked) reverts the entire call. The batch size is bounded by MAX_REFUND_PAGE_SIZE (@custom:reverts InvalidPageSize otherwise). Aggregates the per-entry amounts and transfers once; on transfer failure @custom:reverts RefundFailed. Emits

Note: emits: RefundClaimed once per entry.

function claimRefundsBatch(uint256[] calldata entryIds) external returns (uint256 totalAmount);

Parameters

NameTypeDescription
entryIdsuint256[]List of entry identifiers to claim.

Returns

NameTypeDescription
totalAmountuint256Sum of the credited amounts transferred to the caller.

pendingRefundCount

Returns the number of pending refund entries owed to recipient.

function pendingRefundCount(address recipient) external view returns (uint256 count);

pendingRefundIds

Returns up to limit pending refund entry ids for recipient, starting at offset.

Limit must be in (0, MAX_REFUND_PAGE_SIZE], otherwise @custom:reverts InvalidPageSize.

function pendingRefundIds(
    address recipient,
    uint256 offset,
    uint256 limit
)
    external
    view
    returns (uint256[] memory entryIds);

pendingRefunds

Returns up to limit pending refund entries for recipient, paired with their entry ids.

Limit must be in (0, MAX_REFUND_PAGE_SIZE], otherwise @custom:reverts InvalidPageSize.

function pendingRefunds(
    address recipient,
    uint256 offset,
    uint256 limit
)
    external
    view
    returns (uint256[] memory entryIds, RefundEntry[] memory entries);

refundEntry

Returns a single refund entry by id, or a zero-filled struct if the id is unknown.

function refundEntry(uint256 entryId) external view returns (RefundEntry memory entry);

Events

NativeDepositRecorded

Emitted when a native-token deposit is recorded.

event NativeDepositRecorded(uint256 indexed tokenId, uint256 amount);

NameReleased

Emitted when a token is released into escrow.

event NameReleased(
    uint256 indexed tokenId,
    address indexed recipient,
    address indexed asset,
    uint256 amount,
    uint256 withdrawAvailableAt
);

Parameters

NameTypeDescription
tokenIduint256
recipientaddressRefund recipient snapshotted at release time.
assetaddressDeposit asset. address(0) denotes native token.
amountuint256
withdrawAvailableAtuint256Earliest withdrawal timestamp.

RefundWithdrawn

Emitted when a refund is credited to the recipient's pending balance.

event RefundWithdrawn(
    uint256 indexed tokenId, address indexed recipient, address indexed asset, uint256 amount
);

Parameters

NameTypeDescription
tokenIduint256
recipientaddress
assetaddressRefund asset. address(0) denotes native token.
amountuint256

WithdrawalClaimed

Emitted when a recipient pulls their accumulated pending refund balance.

event WithdrawalClaimed(address indexed recipient, uint256 amount);

RefundCredited

Emitted when a refund is credited to the time-locked refund ledger.

event RefundCredited(
    address indexed recipient,
    uint256 indexed entryId,
    uint256 amount,
    uint64 availableAt,
    uint256 indexed tokenId
);

Parameters

NameTypeDescription
recipientaddressAddress that may claim the entry once availableAt has elapsed.
entryIduint256Newly-assigned identifier for the credited entry.
amountuint256Native value credited.
availableAtuint64Earliest block timestamp at which the recipient may claim.
tokenIduint256Token associated with the credit, retained for traceability.

RefundClaimed

Emitted when a recipient claims a single refund entry.

event RefundClaimed(address indexed recipient, uint256 indexed entryId, uint256 amount);

Parameters

NameTypeDescription
recipientaddressAddress that pulled the entry.
entryIduint256Identifier of the claimed entry, now deleted.
amountuint256Native value transferred to recipient.

NameReclaimed

Emitted when a released token is reclaimed by a new owner via registration.

event NameReclaimed(
    uint256 indexed tokenId, address indexed previousRecipient, address indexed newOwner
);

Parameters

NameTypeDescription
tokenIduint256
previousRecipientaddressAddress that received the refund for the prior registration.
newOwneraddress

CooldownUpdated

Emitted when the cooldown duration for future releases is updated.

event CooldownUpdated(uint256 indexed currentCooldown, uint256 indexed newCooldown);

CrossTierFeePaid

Emitted when a cross-tier fee is paid into the insurance fund.

event CrossTierFeePaid(
    uint256 indexed tokenId,
    address indexed payer,
    address indexed recipient,
    uint256 amount,
    bool isRegistration
);

Parameters

NameTypeDescription
tokenIduint256
payeraddressOriginal msg.sender whose value funded the fee.
recipientaddress
amountuint256
isRegistrationboolTrue when emitted from depositInsurance; false from chargeTransferFee.

InsuranceDraw

Emitted when a withdrawal draws from the insurance fund to cover a shortfall in tokenReserved.

event InsuranceDraw(uint256 indexed tokenId, uint256 amount);

OverpaymentRefunded

Emitted when overpayment is refunded to the payer.

event OverpaymentRefunded(address indexed payer, uint256 amount);

Errors

NotController

Thrown when the caller is not the configured registrar controller.

error NotController(address caller);

NotRegistrar

Thrown when the caller is not the configured registrar.

error NotRegistrar(address caller);

InvalidRecipient

Thrown when the supplied refund recipient is invalid (e.g. zero address).

error InvalidRecipient();

InsufficientValue

Thrown when the attached call value is insufficient to cover the computed charge.

error InsufficientValue();

InsufficientFunds

Thrown when neither tokenReserved nor the insurance fund can cover the refund.

error InsufficientFunds(uint256 tokenId, uint256 owed, uint256 available);

Parameters

NameTypeDescription
tokenIduint256
oweduint256
availableuint256Combined balance available across reserves and insurance.

AssetNotSupported

Thrown when assets being deposited are not supported by the escrow.

error AssetNotSupported(address asset);

InvalidPageSize

Thrown when the configured page size is invalid.

error InvalidPageSize(uint256 limit);

InvalidCooldown

Thrown when the configured cooldown is invalid.

error InvalidCooldown();

CooldownTooLong

Thrown when the supplied cooldown exceeds the contract's configured upper bound.

error CooldownTooLong(uint256 supplied, uint256 maxAllowed);

Parameters

NameTypeDescription
supplieduint256Cooldown value the caller asked for.
maxAlloweduint256Upper bound enforced by the contract.

InvalidAmount

Thrown when the supplied amount is invalid.

error InvalidAmount();

InvalidAsset

Thrown when the supplied ERC20 asset is invalid.

error InvalidAsset();

PositionAlreadyFunded

Thrown when a deposit position is already funded.

error PositionAlreadyFunded(uint256 tokenId);

DepositNotConfigured

Thrown when no deposit is configured for the token.

error DepositNotConfigured(uint256 tokenId);

AlreadyReleased

Thrown when the token has already been released.

error AlreadyReleased(uint256 tokenId);

NotReleased

Thrown when the token has not been released.

error NotReleased(uint256 tokenId);

AlreadyClaimed

Thrown when the refund has already been claimed.

error AlreadyClaimed(uint256 tokenId);

NotReclaimable

Thrown when a token is not in a reclaimable state (released + claimed).

error NotReclaimable(uint256 tokenId);

EscrowNotApproved

Thrown when escrow is not approved to transfer the token.

error EscrowNotApproved(uint256 tokenId);

NotRefundRecipient

Thrown when the caller is not the refund recipient.

error NotRefundRecipient(address caller, uint256 tokenId);

WithdrawalTooEarly

Thrown when withdrawal is attempted before cooldown has elapsed.

error WithdrawalTooEarly(uint256 tokenId, uint256 availableAt, uint256 currentTime);

Parameters

NameTypeDescription
tokenIduint256
availableAtuint256Earliest withdrawal timestamp.
currentTimeuint256Current block timestamp.

RefundFailed

Thrown when a refund transfer fails.

error RefundFailed(uint256 tokenId);

NoPendingWithdrawal

Thrown when claimWithdrawal() is called but the caller has no pending balance.

error NoPendingWithdrawal();

NoSuchRefundEntry

Thrown when a refund entry is referenced but does not exist.

error NoSuchRefundEntry(uint256 entryId);

RefundLocked

Thrown when a refund entry is claimed before its availableAt cooldown has elapsed.

error RefundLocked(uint256 entryId, uint64 availableAt);

NotAcceptedTransfer

Thrown when escrow receives an ERC721 transfer from a non-registrar source.

error NotAcceptedTransfer(address caller);

UnsolicitedDeposit

Thrown when escrow receives a registrar-sourced ERC721 transfer that does not correspond to a live release. Blocks holders who try to push a token into custody by calling @custom:function safeTransferFrom directly without going through @custom:function release, which would otherwise trap the NFT and any deposit permanently.

error UnsolicitedDeposit(uint256 tokenId);

Structs

DepositParams

Parameters for recording a deposit position.

The refund recipient is seeded at deposit time but is not locked: it rebinds to the current NFT holder on every transfer that moves the name off the prior recipient, so the deposit follows the name rather than the original payer. Only the current holder can release into escrow and pull the refund.

struct DepositParams {
    uint256 tokenId;
    address asset;
    uint256 amount;
    address recipient;
}

Properties

NameTypeDescription
tokenIduint256
assetaddressDeposit asset. The zero address denotes the native token.
amountuint256
recipientaddressInitial refund recipient; rebound to the current NFT holder on transfer.

InsuranceDepositParams

Parameters for recording a cross-tier registration fee into the insurance fund.

Funds the shared insurance pool used by withdraw to top up refunds whose per-asset reserve is short; payer is preserved purely for event accounting since the deposit itself is non-refundable.

struct InsuranceDepositParams {
    uint256 tokenId;
    address payer;
    address recipient;
}

Properties

NameTypeDescription
tokenIduint256
payeraddressOriginal msg.sender of the controller's register call.
recipientaddressThe NFT registrant the fee was paid on behalf of.

ChargeTransferFeeParams

Inputs for charging transfer friction and rebinding the escrow position.

The fee charged is the flat reach floor returned by @custom:function PopRules.transferFloor, settled to the insurance fund. The deposit, when present, travels with the NFT: the position is rebound to the recipient so the new holder is the only address that can later release into escrow and unlock the locked value. There is no transfer-time refund path.

struct ChargeTransferFeeParams {
    uint256 tokenId;
    uint256 reachFloor;
    address payer;
    address to;
}

Properties

NameTypeDescription
tokenIduint256
reachFlooruint256Required fee paid by the sender on a downward or cross-reach transfer.
payeraddressOriginal sender of the registrar transfer entrypoint.
toaddressNFT recipient. Becomes the new position recipient whenever a position exists.

ReleasePosition

Canonical escrow state for a token.

Tracks the phased lifecycle as two flags: released flips on release (NFT in escrow, cooldown started); claimed flips on withdraw (refund credited to the pull-payment ledger). The position is deleted on reclaim, freeing the slot for re-registration.

struct ReleasePosition {
    address recipient;
    address asset;
    uint256 amount;
    uint64 withdrawAvailableAt;
    bool released;
    bool claimed;
}

Properties

NameTypeDescription
recipientaddress
assetaddressDeposit asset. address(0) denotes native token.
amountuint256
withdrawAvailableAtuint64Earliest timestamp at which withdrawal is permitted.
releasedbool
claimedbool

RefundEntry

Time-locked refund entry produced when the protocol owes a recipient value outside the registration-overpayment path.

Every credit creates a fresh entry with its own availableAt; later credits do not reset earlier entries' clocks. Recipients claim entries individually or in batches.

struct RefundEntry {
    address recipient;
    uint256 amount;
    uint64 availableAt;
    uint256 tokenId;
}

Properties

NameTypeDescription
recipientaddressAddress that may claim this entry once availableAt has elapsed.
amountuint256Native value credited.
availableAtuint64Earliest block timestamp at which the recipient may claim.
tokenIduint256Token this entry was produced for, retained for traceability.