Skip to content

How to interact with the DNS item contract

Each .ton domain is an NFT item contract deployed by the DNS collection. Every message the contract accepts is documented below, including body layouts and required fields. The TON DNS reference page covers TL-B schemas and auction constants. Source: nft-item.fc (commit 91b5ac2).

The domain item address is deterministic. Compute SHA-256(domain_name) to get the NFT index, then call get_nft_address_by_index(index) on the .ton collection contract.

The collection address is obtained by calling dnsresolve on the root DNS contract (blockchain config parameter #4) with the .ton zone suffix.

Send an internal message with op code 0 to the collection contract. The message body contains the domain name as a text comment. The attached TON value becomes the opening bid.

The collection:

  1. Validates the domain name (4-126 characters, alphanumeric and hyphens)
  2. Computes SHA-256(domain) as the NFT item index
  3. Deploys a new item contract
  4. Starts an auction (auction duration is 1 hour after the initial 12-month rollout period; see nft-item.fc for the interpolation formula)

Minimum starting price depends on domain length (shorter names cost more).

Send an internal message with op code 0 to the item contract. The attached TON value is the bid.

  • Minimum increment: 5% over the current highest bid
  • Bids in the final hour extend the auction by auction_prolongation (3,600 s)
  • Outbid funds are returned to the previous bidder
  • After the auction ends, the next incoming message finalizes the transfer to the winner

Query the current auction state with get_auction_info() before bidding.

Send op::change_dns_record to the item contract. Only the owner can execute this.

Message body layout:

FieldTypeDescription
opuint32change_dns_record op code
query_iduint64Arbitrary identifier for response matching
keyuint256SHA-256 hash of the category name
valuecell ref (optional)TL-B encoded DNS record. Omit to delete.

Categories and their record types:

keyCategoryRecord constructorEffect
SHA-256("wallet")walletdns_smc_address#9fd3Receive funds at <DOMAIN>.ton
SHA-256("site")sitedns_adnl_address#ad01Resolve to a reverse proxy ADNL address
SHA-256("storage")storagedns_storage_address#7473Link a TON Storage bag
SHA-256("dns_next_resolver")dns_next_resolverdns_next_resolver#ba93Delegate subdomains

Send enough TON to cover storage fees to the item contract. The last_fill_up_time is updated when the owner sends op::change_dns_record, op::transfer, op::edit_content, or a bid message after the auction completes.

Call get_last_fill_up_time() to check the last renewal timestamp.

Transfer follows TEP-0062 (op::transfer). Send to the item contract.

FieldTypeDescription
opuint32transfer op code
query_iduint64Arbitrary identifier
new_ownerMsgAddressIntDestination wallet
response_destinationMsgAddressIntAddress for excess TON return
custom_payloadbit (ignored)Always 0 for this contract
forward_amountCoinsTON to forward with ownership notification
forward_payloadcell (optional)Data forwarded to the new owner

Anyone can send op::dns_balance_release to an expired item contract. The attached value must meet get_min_price(), which depends on domain length. This restarts the auction with the sender as the first bidder. The remaining contract balance is returned to the previous owner.

Send op::edit_content to replace the onchain NFT metadata cell. Owner only.

Message body: op (uint32) + query_id (uint64) + content (cell ref, new onchain NFT metadata).

The collection owner (governance) can send op::process_governance_decision (0x44beae41) to an item contract. This operation uses config param 80 to apply governance-level changes.

MethodSignatureReturns
get_nft_data() -> (int, int, slice, slice, cell)(init?, index, collection_address, owner_address, content)
get_domain() -> sliceDomain name string
get_editor() -> sliceCurrent owner address
get_auction_info() -> (slice, int, int)(max_bid_address, max_bid_amount, auction_end_time)
get_last_fill_up_time() -> intTimestamp of last renewal
get_static_data() -> (int, slice)(index, collection_address) via op::get_static_data (0x2fcb26a2)
dnsresolve(slice, int) -> (int, cell)(bits_consumed, record_cell)