Building DEXignation: A Web3 Naming Service on Polygon, From 37 Failing Tests to Mainnet
When we set out to build DEXignation, the goal was simple to state and hard to do: take the proven ENS naming model, bring it to Polygon…
Building DEXignation: A Web3 Naming Service on Polygon, From 37 Failing Tests to Mainnet
When we set out to build DEXignation, the goal was simple to state and hard to do: take the proven ENS naming model, bring it to Polygon, and add the features the next generation of Web3 actually needs — agent payments, duration-tier NFTs, subscriptions, subname commerce — without reinventing the standards that already work.
This is the story of how we got from a test suite with 37 failures to a verified mainnet deployment, and the engineering decisions that shaped the product along the way.
The guiding principle: reference, don’t reinvent
Early on, one principle settled most of our design debates: point to what exists, build only what doesn’t. The Web3 naming space already has battle-tested standards — EIP-634 for text records, EIP-1577 for content hashes, ENSIP-9 for multi-coin addresses. Re-implementing those from scratch would be both wasteful and risky.
So DEXignation completes the full ENS-standard surface rather than competing with it, and reserves original engineering for the genuinely new parts: how a name maps to an AI agent’s payment endpoint, how an NFT card visualizes commitment, how renewals can be automated without a central server.
Starting from red
The first real milestone was unglamorous: a test suite with 37 failures. Three classes of bugs accounted for most of them.
The first was a coin-type encoding mismatch. Our resolver was registering EVM chains under one identifier scheme when the standard expected a plainer one. The fix was isolating coin-type handling into a small utility and aligning it with SLIP-44.
The second was resolver incompleteness — length limits on text and content records, and reads that didn’t account for name expiry. We made every resolver read expiry-aware: once a name lapses, its records return empty. This turned out to matter enormously later, because it’s exactly what prevents a wallet from sending funds to a name whose registration has expired.
The third was a grace-period mismatch between the contract and its tests. We kept the contract’s 70-day grace period as a deliberate product decision and corrected the test expectations.
From there, the suite climbed: 82 passing, then past 100, eventually to 142.
The feature that taught us the most: duration-tier NFT cards
Every .dex name is an NFT, and we wanted the NFT’s artwork to mean something. The idea: color the card by how long the owner has committed to the name. A one-year holder gets a quiet charcoal card; a fifteen-year holder gets gold.
This sounds simple. It wasn’t — because the rules for how the color behaves encode a product philosophy, and we went back and forth on them.
The breakthrough was framing the color as a “best ever” badge rather than a live countdown. The tier ratchets up when you register or renew for longer, and it never ratchets down as time passes — so a fifteen-year gold card stays gold years later. The only exception is actual expiry, which turns the card red as a clear warning. This reconciles two instincts that felt contradictory at first: “buying long should be rewarded permanently” and “an expired name should be obvious.”
Two engineering decisions fell out of this:
On-chain SVG, no filters. The card is generated entirely on-chain as vector graphics. We deliberately avoided SVG <filter> effects — they render inconsistently across wallets and marketplaces and cost more gas. Gradients and a radial shine carry the premium look while staying deterministic and cheap.
A boundary bug worth remembering. When we mapped purchase duration to tier, we initially used a strict less-than comparison. The result: buying exactly one year landed you one tier too high, and the same off-by-one rippled through every tier. The symptom was unmistakable in testing — five of six tier colors were each shifted up by one, while only the top tier happened to look correct. Switching to less-than-or-equal fixed it. On a normal app this would be a quick patch; on an immutable NFT contract, catching it before deployment was the difference between a clean launch and permanently wrong artwork.
Bridging to the agent economy, not competing with it
By 2026, AI agents transacting on their own behalf stopped being speculative. ERC-8004 gave agents an identity layer; x402 gave them an HTTP-native stablecoin payment standard backed by major players.
We had a choice: build our own agent payment rails, or bridge to the emerging standards. We bridged. A .dex name can now carry a record pointing to an agent’s identity and payment endpoint, and resolution is expiry-aware like everything else. The name becomes the human-readable handle in front of agent infrastructure — which is exactly the role a naming service should play.
Permissionless auto-renewal
Letting names auto-renew is an old idea, but doing it without a central server is harder. Our approach: the owner pre-approves a stablecoin and registers renewal terms. After that, anyone can trigger the renewal — a keeper, a backend cron, the owner themselves. The contract re-validates the renewal window and re-checks the price against the owner’s cap before pulling funds, so permissionless never means unsafe. It even handles USDT’s non-standard approve so consecutive renewals don’t break.
The deployment gauntlet
Shipping to mainnet surfaced two issues that unit tests can’t catch.
The first was a compilation profile mismatch. Hardhat 3 uses separate build profiles — and Ignition deploys with the production profile, which didn’t inherit the viaIR setting our tests used. The contracts compiled fine for testing but failed to deploy with a “stack too deep” error. The fix was defining the production profile explicitly so deployment compiled identically to testing — guaranteeing the code we tested is the code we shipped.
The second was a dead oracle feed. On the Amoy testnet, the documented Chainlink POL/USD feed had stopped responding — calling it reverted entirely. This blocked our price conversion from working, even though our code was correct. The diagnosis mattered: was it our bug or the testnet’s infrastructure? We confirmed it was the feed by calling it directly, then deployed our own mock aggregator on the testnet to substitute for the dead feed — swapping only that one external dependency, leaving the real conversion logic, registration, NFT generation, and resolution all under genuine test.
With the mock feed in place, the full flow finally ran end-to-end on a live network: prices converted across all five durations, a name registered through commit-reveal, the NFT rendered with the correct charcoal tier, text records and multi-coin addresses set and read back. Then mainnet, where the real Chainlink feed was alive and well — prices converted correctly on the first try.
What we learned
A few things stand out.
Testing earned its keep. Every bug we caught — the coin-type mismatch, the off-by-one tier boundary, the compilation profile, the dead feed — would have been far more expensive after launch, and some would have been unfixable on immutable contracts.
The “reference, don’t reinvent” principle kept the surface area honest. We didn’t claim to invent text records or agent payment standards; we completed the standards and bridged to them. The genuine originality lives in the smaller, specific mechanisms — the tier-ratchet rule, the name-to-agent bridge, the permissionless-but-safe renewal.
And the distinction between unit tests and live-network verification is real. The contracts passed 142 unit tests and still surfaced two deployment-only issues. Walking the full path on a testnet before mainnet wasn’t ceremony — it was the step that caught what nothing else could.
DEXignation is now live on Polygon mainnet, source-verified, with the full feature set running. The naming layer is, in a sense, the easy-to-describe part. What it enables next — agent commerce, on-chain identity, a name you actually own — is where it gets interesting.
메타데이터
- post_id
- db8c683efbe2
- slug
- building-dexignation-a-web3-naming-service-on-polygon-from-37-failing-tests-to-mainnet-db8c683efbe2
- url
- https://medium.com/dexignation/building-dexignation-a-web3-naming-service-on-polygon-from-37-failing-tests-to-mainnet-db8c683efbe2
- canonical_url
- https://medium.com/dexignation/building-dexignation-a-web3-naming-service-on-polygon-from-37-failing-tests-to-mainnet-db8c683efbe2
- author_url
- https://medium.com/@punditcode
- status
- ok
- fetched_at
- 2026-06-20 20:29:01