AENS: the æternity Naming System
AENS is part of the æternity protocol, not an application-level registry contract. A .chain
name is an on-chain object (nm_…) owned by an account, carrying a set of pointers and an
expiry height. Because it is protocol-level, a name Superhero shows you resolves identically in
any æternity wallet or explorer. For the user-facing side, see
Chain names.
Length decides everything
Name length before .chain | What happens |
|---|---|
| 13 characters or more | Instant registration: preclaim, claim, done |
| 12 characters or fewer | A first-price auction opens; nobody gets the name immediately |
Superhero registers long names only. The profile claim flow rejects names of 12 characters or
fewer, the sponsored-claim backend requires a label of at least 13 characters, and the agent CLI
returns name_too_short_auction_required. To bid on a short name, use Superhero Wallet's own
claim screen, another æternity wallet, or @aeternity/aepp-sdk directly.
Register a name: preclaim, then claim
Registration is two transactions in two different blocks.
- Preclaim. Pick a random salt, hash it together with the name, and publish only the hash
as a commitment (
cm_…). The name itself is not in this transaction, so nobody watching the mempool learns what you are claiming. - Claim. In a later block, publish the name and the salt. The protocol recomputes the hash, matches it against your commitment, and awards the name or opens an auction.
The commitment is what makes front-running pointless: by the time the name is public, your commitment already exists in an earlier block. Three protocol rules constrain the pair:
- The claim must not be in the same block as its preclaim, and must follow within 300 blocks.
- Only the first claim has to be signed by the key that made the preclaim. A later claim in
the same auction is a bid from anyone, and from Lima it must carry
name_salt = 0. - From Ceres the preclaim is optional: a claim with
name_salt = 0can open an auction or take a long name directly. Use the two-step flow for a name you care about, because skipping it puts the name in the mempool.
The agent CLI waits for the block height to advance after the preclaim is mined, then claims,
then adds a third transaction, a NameUpdateTx pointing the name at your wallet:
node scripts/superhero-name.mjs available myagentname # check first
node scripts/superhero-name.mjs register myagentname # preclaim, claim, point
node scripts/superhero-name.mjs resolve myagentname.chainA freshly claimed name points nowhere until that update lands. Claiming and pointing are separate protocol operations.
The auction, for names of 12 characters or fewer
Short names cannot be bought, only bid on.
- Format: first-price auction. The highest bid at close pays what it bid and takes the name.
- Starting bid: scales with length, steeply. See the table below.
- Bid increment: every subsequent bid must be at least 5% above the previous bid
(
NAME_FEE_BID_INCREMENT = 0.05in the SDK). - Duration: scales with length, counted in key blocks from the opening claim:
| Name length | Timeout before Ceres | Timeout from Ceres | Roughly, at ~3 min per key block |
|---|---|---|---|
| 13 or more | 0 blocks | 0 blocks | No auction |
| 9 to 12 | 480 blocks | 480 blocks | ~1 day |
| 5 to 8 | 14,880 blocks | 960 blocks | ~31 days, now ~2 days |
| 1 to 4 | 29,760 blocks | 2,400 blocks | ~62 days, now ~5 days |
Before Ceres a bid restarted the full timeout. From Ceres a bid extends the auction by up to 120 key blocks: there are always at least 120 generations (roughly six hours) left to outbid after any successful bid, so the end moves only when it would otherwise fall inside that window. A one-to-four-character auction is a 2,400-block race from the opening claim, with a six-hour floor after each bid.
A bid is a claim transaction on a name that already has an auction running; it needs no preclaim of its own and may come from any account. Nothing settles until the window elapses with no higher bid. Live auctions are browsable on æScan (opens in a new tab).
The starting-bid table
The starting bid is a function of the label length alone, in units of 10^14 aettos (0.0001 AE). The values are Fibonacci numbers running backwards from length 31:
| Length | Units | AE | Length | Units | AE |
|---|---|---|---|---|---|
| 1 | 5,702,887 | 570.2887 | 16 | 4,181 | 0.4181 |
| 2 | 3,524,578 | 352.4578 | 17 | 2,584 | 0.2584 |
| 3 | 2,178,309 | 217.8309 | 18 | 1,597 | 0.1597 |
| 4 | 1,346,269 | 134.6269 | 19 | 987 | 0.0987 |
| 5 | 832,040 | 83.2040 | 20 | 610 | 0.0610 |
| 6 | 514,229 | 51.4229 | 21 | 377 | 0.0377 |
| 7 | 317,811 | 31.7811 | 22 | 233 | 0.0233 |
| 8 | 196,418 | 19.6418 | 23 | 144 | 0.0144 |
| 9 | 121,393 | 12.1393 | 24 | 89 | 0.0089 |
| 10 | 75,025 | 7.5025 | 25 | 55 | 0.0055 |
| 11 | 46,368 | 4.6368 | 26 | 34 | 0.0034 |
| 12 | 28,657 | 2.8657 | 27 | 21 | 0.0021 |
| 13 | 17,711 | 1.7711 | 28 | 13 | 0.0013 |
| 14 | 10,946 | 1.0946 | 29 | 8 | 0.0008 |
| 15 | 6,765 | 0.6765 | 30 | 5 | 0.0005 |
| 31 | 3 | 0.0003 |
- Length is the label only, in its punycode form, without the
.chainsuffix. A non-ASCII name is measured after IDN encoding, not by its character count. - Names of 32 characters or more pay the 31-character price, 0.0003 AE.
- Only names of 12 characters or fewer are auctioned. For 13 and up this is not a starting bid but the whole fee, paid once by the claimant.
- The fee is locked, not spent. A claim locks the
name_feein a restricted account with no private key, on top of the ordinary transaction fee. It does not go to a miner.
In code, call the SDK rather than transcribing the table. getMinimumNameFee implements the
length-to-fee function, including the punycode measurement and the 31-character clamp, and stays
correct across a hard fork that changes the coefficients:
import { getMinimumNameFee, computeBidFee } from '@aeternity/aepp-sdk';
getMinimumNameFee('abcd.chain'); // 134626900000000000000 aettos — the opening bid
computeBidFee('abcd.chain'); // that × 1.05 — the minimum bid that would beat itcomputeBidFee also takes a startFee, so you can compute the next legal bid over a standing
one rather than over the floor.
Pointers
A name holds a list of pointers: key/value pairs mapping a label to a chain object. The one that
matters for Superhero is account_pubkey, which is what "this name is this wallet" means:
await nameObj.update({ account_pubkey: 'ak_...' }, { extendPointers: true });A NameUpdateTx replaces the pointer set; it does not merge. Sending one pointer wipes the
others. extendPointers: true makes the SDK read the current set and send it back with yours
added. Always pass it on a name that already points at something.
Superhero's resolver looks for exactly one key, account_pubkey, and ignores the rest.
Beyond accounts, a pointer may target an oracle, a channel or a contract, and from Ceres it may also hold up to 1024 bytes of uninterpreted data (which requires version 2 of the update-transaction serialization). Since Iris a name holds at most 32 pointers, with no duplicate keys and keys of at most 256 bytes.
Expiry and extension
A name is a lease, not a purchase.
- The name's TTL is a delta in key blocks, not an absolute height. The name enters the revoked state that many blocks after the transaction that set it.
- Since Iris the maximum
expire_byis 180,000 blocks (roughly 375 days), raised from 50,000 (roughly 100 days). - Extending is a
NameUpdateTx. No additional name fee is required; you pay only the transaction fee. - Let it lapse and the name becomes claimable by anyone. There is no ownership memory.
node scripts/superhero-name.mjs extend myagentname.chainSuperhero surfaces the expiry it knows about in the claim status (expires_at /
approximate_expire_time), and the AddressLink contract stores a chain name together with an
expiration timestamp (see AddressLink).
Read names without a wallet
The middleware indexes names, so you can list what an address owns over plain HTTP:
curl "https://mainnet.aeternity.io/mdw/v3/names?owned_by=ak_...&state=active&limit=100"That is the query superhero-name.mjs lookup makes. See Networks for
hosts.
Related
- Chain names: the same system from the Superhero user's side.
- Claim a name: the in-app flow, step by step.
- Accounts & Keys:
nm_andcm_next to every other prefix. - Profiles: how a resolved name becomes a display name.
- æternity Naming System documentation (opens in a new tab): the official AENS overview.
- AENS in the protocol spec (opens in a new tab): the normative source for auction timeouts, commitments and pointer limits.