How to resolve BNS X names


As mentioned here, we’re working on a BNS upgrade to overcome the challenges that are currently holding BNS back. We’re calling this upgrade BNS X.

What BNS X functionality will be available in this first release?

The major feature in this first release is the ability to ‘wrap’ an existing BNS name in a smart contract, which allows users to consolidate and manage multiple names under one wallet. This, combined with SIP9 compliance of these BNS X names, will automatically open up a ton of functionality to apps that support the Stacks NFT standard (like marketplaces and wallets).

What is changing on BNS v1?


What is changing with BNS X?

Because users will be wrapping their BNS name and transferring it to a smart contract, there will be a mismatch between the on-chain lookup of a BNS name and the ‘true’ owner.

Example: I wrap hank.btc:

  • If you query the BNS contract, the owner of hank.btc will be a contract principal
  • If you query my address in BNS, it’ll show that I don’t own any names

Users who wrap their names will want to still enjoy the benefits of showing their name ownership in apps. Similarly, users will want to know the true owner of a given name, even if it is wrapped.

To solve for this, we have a ‘registry’ contract that stores the relationship between a BNS name and a BNS X name. To get the true owner of a name, you can lookup who owns the ‘wrapped’ name.


  • I wrap hank.btc
  • I minted the nft .bns-x::names with some integer ID
  • An event is propogated with the data { wrapped-id: id, name: name, wrapper-contract: principal }
  • Your systems store this mapping and are able to resolve that I own hank.btc

It’s possible for a wrapped name to be transferred. In that case, your app should resolve the owner of a name to the current owner of the wrapped BNS X name.

  • Example: I mint hank.btc, and then transfer it to Alice. If you lookup the owner of the “wrapped” hank.btc, you’ll show Alice as the owner.

Primary names are a mechanism to keep the ‘one-name-one-owner’ behavior that allows apps to show a single name for a STX address. In our protocol, if anyone owns a BNS X name, they’ll have a primary name stored on-chain. Users don’t have to set this manually, although they can change their primary name if they own multiple BNS X names.

I’m an app: What do I need to do to resolve BNS X names?

On day one, we’ll provide an API endpoint that mimick the Stacks Blockchain API BNS endpoints 1-for-1. For BNS-related API calls, you’ll only need to update your app to query our URL for those endpoints.

We will extend the current API interface to also include BNS X-specific data, like a user’s primary name and the NFT’s integer ID.


  • I own hank.btc, and I’ve wrapped it
    • /v1/names/hank.btc will return me as the owner, not the wrapper.
    • /v1/addresses/stacks/SP123... will return hank.btc as the name.
      • If will also return other names if I own multiple wrapped names.
  • Alice owns alice.btc, and it’s not wrapped
    • The API endpoints described above will resolve exactly as they do today.

I’m an NFT wallet or marketplace: What do I need to do to list BNS X names properly?

If you support SIP9 NFTs: Nothing. You are all set.

I’m the Hiro API: What can I do to help?

We are aiming to work together with Hiro and the community to get BNS X name resolution included by default in the Stacks Blockchain API repo. With that change, apps that use that API for BNS info won’t have to do anything to allow users to resolve their names properly.

What happens when I do an on-chain transfer of a primary name out from under the wrapped names? ie Wallet1Account1-on chain(‘primary’) bns = dan.btc, wrapped = ‘foo.btc’, ‘bar.btc’ … now I transfer ‘dan.btc’ to Wallet2Account7.

If I call `/v1/addresses/stacks/<wallet 1, account 1> will I get a “blank” name for the “primary name” (ie 3 names returned)? Or will I only get the 2 wrapped names that remain?

Thanks for putting together this proposal @hank

I have a question regarding alternate approaches to wrapping. You must have considered the following approach already, but I’m curious why we’re not going with something similar.

What if we create a new BNSv2 contract which:

  1. Is SIP-9 compatible.
  2. Allows multiple names per address.
  3. Look-ups pass through to BNSv1 if name isn’t registered on v2.
  4. Names can only be registered on BNSv2 if it hasn’t already been registered via BNSv1.
  5. Users can migrate their name to BNSv2 by calling a function on the v2 contract which will call the name-revoke function on BNSv1 to make it unresolvable, and then mint the name on BNSv2.
  6. Users can continue to register and use v1 names if they wish. The community would gradually migrate all of the tooling and frontends to v2.

I’m not sure if I’m interpreting your question correctly, but I think what you’re asking is:

  • I wrap dan.btc
    • Now I own this on BNS X, and the “legacy” BNS name is owned by a wrapper contract
  • I transfer dan.btc
  • Now, if you request /v1/address/stacks/wallet-1, you’ll have no names

Or if you’re asking about if you own multiple BNS X names?

If so, if you own multiple BNS X names, and transfer the “primary”, the BNS X contracts will automatically set your “next” name as primary. There’s no way of transferring without this logic getting triggered. If you don’t own any BNS X names, and you own a “legacy” BNS name, then I think we’ll have the primary field in the API return your legacy name. I’m not 100% sure on that, but no matter what the names array will be backwards compatible, so you can have something like:

displayName = data.primaryName || data.names[0]

Interesting - this is definitely very similar to our approach. Keep in mind that what we’re building is a “gradual” approach, and we want to make the transition as frictionless as possible, especially to start. At launch we’re only allowing BNS X names to be minted if you own the v1 name. We don’t yet want to get in a “state fork” where the same name can have different owners on v1 and v2. Similarly, forcing users to wrap (instead of name-revoke/burning it) allows users to get the “best of both worlds” - they can go back to v1 if needed. It also should make BNS X names more valuable , because it comes “bundled” with ownership of the v1 name.

Obviously would love to chat more with you about this!

Good mention thank you!

So there would eventually be a BNS v2 contract and the only difference between your proposal and what I posted is the wrapping vs name-revoke.

How would the existing Stacks node API handle ownership of BNS v2 NFTs? Since the names are owned by contracts and not directly by the wallet address. As wallets and other apps currently use the Stacks node API to determine NFT ownership, a wrapped BNS name would not show up under assets on look up. Is there any work being done on the API side at the same time to support this?

Also this approach that will break BNS functionality in production apps. Currently Xverse, and other apps like Gamma, use the owner address of the BNS name as the recipient for STX token and NFT transfers. If the owner of the BNS name is a contract, this functionality would break.

Yeah, I totally understand this concern. That’s exactly why we’re trying to prioritize working with integrators before launching, along with hosting a backwards-compatible API. The ideal situation is of course to also have the Stacks API support BNSx, which we are working towards.

1 Like

Okay, let me know how we can help.

1 Like

There is no way to avoid a state fork here, as @yukan pointed out. This wrapper approach is asking for trouble when the alternative is so much simpler. The new contract should mint the new name and revoke the old one with the following logic.

  • If name does not exist on old contract, mint it there first.
  • If user owns old name, mint new name.
  • Revoke old name.

This can all be done in one transaction and aborted in case of failure. The standard API endpoint should be updated to check the new contract first and fallback to the old contract.

Take care not to rush this out without extensive peer review.

1 Like

Could you elaborate more on what you mean in regards to asking for trouble? Trouble in the short term or long term?

I think I’d definitely agree that a 1-tx name revoke plan is more simple from a technical point of view. Our thought is not that wrapping is technically simpler (definitely isn’t), but that is more likely to lead to long-term success. If we launched today and said “here’s this thing, please destroy your BNS name to use it”, would that lead to more users migrating? My guess is that would be “no” - the guess is that users are more likely to adopt a gradual approach vs something that gives the benefits with much less risk. Then, over time, a state fork has greater chance of success once there is momentum behind it.

Thank you so much to @jeff and @hank for all of their work on this.

I was having trouble finding docs and code…if anyone else is, here’s a link: - thanks to @yukan for giving me this.

Initially, I share similar questions to the ones @yukan brought up. Will hold off on commenting further until I’ve looked at this in more detail.

Both. BNS on Stacks is already fragile with an unstable API.

  • It resolves the wrong owner in various circumstances [1].
  • It resolves revoked names that should no longer resolve [2].
  • It resolves some accounts to multiple addresses [3].

This is exacerbated by attempts to wrap names like Gamma has done, which results in names canonically resolving to contracts rather than the intended address, except on supported platforms (Gamma in this case). Seeing the name resolve correctly on the platform after listing for sale gives the user the false expectation that it should continue functioning in the same way as usual; but if that user then has some token or NFT transferred to the name by some user on another platform where it is not supported like Hiro, Xverse, or Tradeport, it would instead go to the contract and become permanently irretrievable. Gamma gets a pass here though because they did not ask other developers to adopt their wrapper sales contract and thus risk poisoning the entire ecosystem.

That is the real problem and leads back to the issue of the API. Dependence on an additional third-party API poses unacceptable compounding risks. If the standard API is not reliable, then the new API is already shipped in a broken state; to say nothing of the additional counterparty risk.

The intended outcome here is unclear to me.

  • If the new system is not expected to be adopted by the Stacks API, then it should be treated as a niche curiosity until the real upgrade, so developers and users should not adopt it en masse.
  • If the new system is expected to be adopted by the Stacks API, then just do that and forget the unnecessary interim wrapper approach.

I like this idea in concept as a slightly better version of Gamma’s sales contracts, but there are too many unknowns arising from the API issue.

1 Like

Thanks for raising these concerns, @Babo. If I can attempt to summarize them:

  1. The use of additional APIs will exacerbate the bugginess of BNS data as provided to wallets and apps alike
  2. Their use will also incur greater counterparty risk
  3. By wrapping names in BNSx contracts, apps may accidentally facilitate the transfer of assets to wrapper contracts, where they get “trapped”, by mistaking them for end-user principals

Please let me know if I missed any or didn’t capture these right.

I’m certainly sympathetic to these concerns, though I’m skeptical that they’re dealbreakers for moving forward here with some initial integrations (at least on the Hiro Wallet side).

Per #1, are there other BNS-related bugs that have impacted the Stacks Blockchain API over the past year in addition to the three here you’ve listed? Two of them appear resolved already, with the third reported just this week.

If there were a significantly more – especially ones that have remained unresolved for extended periods of time – I’d also be concerned about the complexity of another API for BNS data.

Per #2, this is true in principle, though Mechanism is a relatively well-known member of the Stacks community so the risk seems low to me in this case, especially if the idea here is that we’ll rely on their API only in the short-term until Hiro integrates the functionality directly into the Stacks Blockchain API.

I’ll check with the API team at Hiro to see just where this functionality factors into their roadmap so we have a better sense of that timing and duration of this risk.

Per #3, do we know of real-world use cases where this could actually happen? In both Hiro Wallet and Xverse, it appears that sends aren’t permitted to contracts in any case (so the BNS lookup feature does indeed break, but no funds are put at risk):

Screenshot 2023-02-09 at 15.15.23


However, granted that such a transfer does end up happening, could the wrapper contract itself could support withdrawals on the part of the name owner of any standardized FTs or NFTs that have been sent to it?

Finally, as far as the “extensive peer review” you mention, do you recommend we follow a particular process or get a particular set of eyes on BNSx?

I’m sympathetic with the idea of moving (relatively) quickly in trying out BNSx and seeing how it performs in real life, since pre-launch discussions around BNS have stagnated historically. And it does seem best that folks try it on for size as an optional enhancement before needing to revoke their BNS (v1) names and commit more fully to BNSx. That way we also avoid the need to choose “either/or” as a community.

However, we certainly want to minimize anywhere things can go wrong, especially if users’ funds could be at risk. So please do continue to pressure test all of this. :pray:


Is it the case that funds sent to a contract principal resolved by a BNSx name are irretrievable, or am I misunderstanding @Babo’s comments?

Yes, that’s correct. This is in some sense “unlikely” due to the frontend guardrails mentioned by mark, but neglects Murphy’s law.

Technically, BNSX could implement some “escape hatch” in the wrapper contracts for the owner to retrieve any misplaced assets, but this would add yet another layer of complexity.

Meanwhile, we can add another unforeseen problem to the list: [Hiro wallet lost subdomain name display in v3.33.0 for firefox, chrome · Issue #3075 · hirosystems/stacks-wallet-web · GitHub]


Are Group ID’s useful? I was told this used to be done in/by Radiks.

Replying here to say that we need to propose a specific upgrade that doesn’t have all of the problems and poor incentives of BNSx. It is not an upgrade; it is a downgrade. We at Trajan will support a better version of BNS that enables it to function as an identity and naming system.

A few other Stacks apps have told me the same. So if we get a specific proposal, several of us will adopt it.

I don’t try and position BNSx as an “upgrade” - just as a system that work alongside BNS without any changes to the base layer. I’m fully supportive of a proper BNS upgrade and more than happy to contribute to one in any way necessary.

In your first post you wrote, " As mentioned here we’re working on a BNS upgrade to overcome the challenges that are currently holding BNS back. We’re calling this upgrade BNS X."
I’ve seen "BNSx upgrade language elsewhere.

But I’m glad you want to do a proper BNS upgrade, as you have a lot of skills and experience to make it happen. Let’s make it a priority to get something proposed? I’m not a dev so my contribution will focus on end-goals and adopting the upgrade.