meganames

Installation
SKILL.md

MegaNames (.mega) Development Skill

What This Skill Is For

Use this skill when the user asks for:

  • Registering or renewing .mega names on MegaETH
  • Resolving names to addresses (forward) or addresses to names (reverse)
  • Setting text records (avatar, social links, bio)
  • Creating or revoking subdomains
  • Selling subdomains via the marketplace (SubdomainRouter)
  • Token-gating subdomain purchases
  • Linking Warren Protocol on-chain websites to .mega names
  • Building frontends that integrate MegaNames resolution
  • Querying name ownership, expiry, or marketplace state

Chain Configuration

Network Chain ID RPC Explorer
Mainnet 4326 https://mainnet.megaeth.com/rpc https://mega.etherscan.io
Testnet 6343 https://carrot.megaeth.com/rpc https://testnet-mega.etherscan.io

Contract Addresses (Mainnet)

Contract Address
MegaNames 0x5B424C6CCba77b32b9625a6fd5A30D409d20d997
USDM 0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7
Renderer 0x8d206c277E709c8F4f8882fc0157bE76dA0C48C4
SubdomainRouter 0xdB5e5Ab907e62714D7d9Ffde209A4E770a0507Fe
SubdomainLogic 0xf09fB5cB77b570A30D68b1Aa1d944256171C5172
Fee Recipient 0x25925C0191E8195aFb9dFA35Cd04071FF11D2e38

Testnet: MegaNames 0x8F0310eEDcfB71E5095ee5ce4f3676D9cEA65101 · MockUSDM 0xa8a7Ea151E366532ce8b0442255aE60E0ff2F833

Frontend: dotmega.domains

Default Stack Decisions (Opinionated)

1. Use eth_sendRawTransactionSync for all writes

MegaETH returns receipts in <10ms via EIP-7966. No polling needed.

2. Use registerWithPermit when possible

Single-tx registration via ERC-2612 permit — better UX than approve + register.

3. Use on-contract fee calculation

Call calculateFee(labelLength, numYears) instead of replicating discount logic locally.

4. Resolve via tokenId, not string lookups

Compute the tokenId client-side, then call addr(tokenId). Never send raw label strings to read functions.

5. Labels are always lowercase

Normalize labels with .toLowerCase() before hashing. The contract enforces [a-z0-9-] with no leading/trailing hyphens. Max 255 characters.

Token ID Computation

Names map to ERC-721 token IDs via ENS-style namehashing:

import { keccak256, encodePacked, toBytes } from 'viem'

const MEGA_NODE = keccak256(encodePacked(['bytes32', 'bytes32'], [
  '0x0000000000000000000000000000000000000000000000000000000000000000',
  keccak256(toBytes('mega'))
]))
// = 0x892fab39f6d2ae901009febba7dbdd0fd85e8a1651be6b8901774cdef395852f

function getTokenId(label: string): bigint {
  return BigInt(keccak256(encodePacked(['bytes32', 'bytes32'], [
    MEGA_NODE, keccak256(toBytes(label.toLowerCase()))
  ])))
}

// Subdomain tokenId uses parent tokenId as the node
function getSubTokenId(parentTokenId: bigint, subLabel: string): bigint {
  const parentBytes = `0x${parentTokenId.toString(16).padStart(64, '0')}` as `0x${string}`
  return BigInt(keccak256(encodePacked(['bytes32', 'bytes32'], [
    parentBytes, keccak256(toBytes(subLabel.toLowerCase()))
  ])))
}

Fee Schedule

All fees in USDM (18 decimals).

Label Length Annual Fee Multi-Year Discounts
1 char $1,000 2yr: 5%, 3yr: 10%, 5yr: 15%, 10yr: 25%
2 chars $500 Same discount tiers
3 chars $100 Same discount tiers
4 chars $10 Same discount tiers
5+ chars $1 Same discount tiers

Core Operations

Register a Name

// 1. Calculate fee
const fee = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'calculateFee',
  args: [BigInt(label.length), BigInt(numYears)]
})

// 2. Approve USDM
await walletClient.writeContract({
  address: USDM, abi: erc20Abi, functionName: 'approve',
  args: [MEGANAMES, fee]
})

// 3. Register
await walletClient.writeContract({
  address: MEGANAMES, abi, functionName: 'register',
  args: [label, ownerAddress, BigInt(numYears)]
})

Register with Permit (Single Transaction)

megaNames.registerWithPermit(
    "yourname",
    msg.sender,
    1,         // numYears
    deadline,  // permit deadline
    v, r, s    // ERC-2612 permit signature
);

Resolve Name → Address

const tokenId = getTokenId("bread")
const address = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'addr', args: [tokenId]
})

Resolve Address → Name (Reverse)

const name = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'getName', args: [userAddress]
})
// Returns "bread" or "" if no primary name

Set Text Records

await walletClient.writeContract({
  address: MEGANAMES, abi, functionName: 'setText',
  args: [tokenId, "com.twitter", "@yourhandle"]
})

Standard keys: avatar, url, com.twitter, com.github, com.discord, org.telegram, description

Create Subdomains (Free)

// Parent owner creates: blog.yourname.mega
await walletClient.writeContract({
  address: MEGANAMES, abi, functionName: 'registerSubdomain',
  args: [parentTokenId, "blog"]
})

// Subdomains are full ERC-721 tokens with their own resolution + records
// Nested up to 3 levels: sub.parent.mega → child.sub.parent.mega

Subdomain Marketplace

Name owners sell subdomains through the SubdomainRouter. 97.5% to owner, 2.5% protocol fee.

Seller Setup

const ROUTER = '0xdB5e5Ab907e62714D7d9Ffde209A4E770a0507Fe'
const LOGIC  = '0xf09fB5cB77b570A30D68b1Aa1d944256171C5172'

// 1. Approve router (one-time)
await walletClient.writeContract({
  address: MEGANAMES, abi: erc721Abi, functionName: 'setApprovalForAll',
  args: [ROUTER, true]
})

// 2. Set price (min $0.01 USDM)
await walletClient.writeContract({
  address: LOGIC, abi: logicAbi, functionName: 'setPrice',
  args: [parentTokenId, parseUnits('1', 18)] // $1 USDM
})

// 3. Enable sales (mode: 0=open, 1=token-gated)
await walletClient.writeContract({
  address: ROUTER, abi: routerAbi, functionName: 'configure',
  args: [parentTokenId, payoutAddress, true, 0]
})

Buyer Flow

// 1. Get quote
const [allowed, price, protocolFee, total] = await publicClient.readContract({
  address: ROUTER, abi: routerAbi, functionName: 'quote',
  args: [parentTokenId, "sublabel", buyerAddress]
})

// 2. Approve USDM
await walletClient.writeContract({
  address: USDM, abi: erc20Abi, functionName: 'approve',
  args: [ROUTER, total]
})

// 3. Register
await walletClient.writeContract({
  address: ROUTER, abi: routerAbi, functionName: 'register',
  args: [parentTokenId, "sublabel", '0x0000000000000000000000000000000000000000'] // referrer
})

Token Gating

// Require buyers to hold a specific NFT/token
await walletClient.writeContract({
  address: LOGIC, abi: logicAbi, functionName: 'setTokenGate',
  args: [parentTokenId, tokenContractAddress, 1n] // min balance
})
// Use mode=1 in configure() to enable the gate

Batch Registration

// Register up to 50 subdomains in one tx
string[] memory labels = new string[](3);
labels[0] = "alpha"; labels[1] = "beta"; labels[2] = "gamma";
uint256[] memory tokenIds = router.registerBatch(parentTokenId, labels, address(0));

Warren Contenthash (On-Chain Websites)

Link a .mega name to a Warren Protocol on-chain website:

// Link Warren NFT (isMaster: true for Master, false for Container)
await walletClient.writeContract({
  address: MEGANAMES, abi, functionName: 'setWarrenContenthash',
  args: [tokenId, warrenTokenId, true]
})

// Read: returns { warrenTokenId, isMaster, isWarren }
const warren = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'warren', args: [tokenId]
})
// Contenthash format: 0xe9 + 01(master)/02(container) + 4-byte warrenTokenId

Expired Names & Premium Decay

Names expire after their registration period. After a 90-day grace period, names become available with a Dutch auction premium decaying linearly from $10,000 → $0 over 21 days.

const premium = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'currentPremium', args: [tokenId]
})
// Premium is added on top of base registration fee

Enumeration & Stats

// All names owned by an address
const tokenIds = await publicClient.readContract({
  address: MEGANAMES, abi, functionName: 'tokensOfOwner', args: [userAddress]
})

// Global stats
const registered = await publicClient.readContract({ address: MEGANAMES, abi, functionName: 'totalRegistrations' })
const volume = await publicClient.readContract({ address: MEGANAMES, abi, functionName: 'totalVolume' })

MegaETH-Specific Notes

  • Gas estimation: Always use eth_estimateGas via RPC — local Foundry estimation may undercount on MegaETH
  • Instant receipts: Use eth_sendRawTransactionSync (EIP-7966) for immediate confirmation
  • USDM: 18 decimals, ERC-2612 permit supported
  • No commit-reveal: MegaETH block times (~10ms) make front-running impractical

Full ABI Reference

See AGENTS.md in the repo root for the complete function reference, events, and integration patterns.

Installs
1
GitHub Stars
1
First Seen
Mar 17, 2026