Unifying Polkadot ecosystem address format

Unifying Polkadot address format

This initiative falls under the UX Bounty scope and the necessary resources will be covered by its budget. You can find all relevant materials here.

As of today, there are over 150 registered entries in the Polkadot ecosystem using different SS58 address prefixes. This creates significant fragmentation, as each prefix represents an entity with a unique address format. Some projects, like Moonbeam and Myth, don’t even use this registered prefix as they are using entirely different account systems.

This fragmentation complicates the user experience, as users are often confused about why they need different addresses across the ecosystem or why their address changes depending on the wallet or dApp they use. This, in turn, puts pressure on developers who are trying to build the best possible experiences. While there may be valid reasons for using different prefixes, we will walk through these and propose a solution that addresses the underlying issues in a more streamlined way.

The problem summary

As discussed in the forum post in more detail, the current approach creates numerous UX challenges, and there are still problems it doesn’t address, including:

  1. Complicating the user experience for everyone in the ecosystem—both users and developers.
  2. Users accidentally sending assets to the wrong chain, whether it’s an exchange account, hardware wallet, or proxy. Fortunately, the last two are being addressed.

Currently, we primarily see two types of address formats (and wallets) in use with ecosystem front ends:

  1. Substrate-based SS58 formatted addresses:

    (e.g., 16ZL8yLyXv3V3L3z9ofR1ovFLziyXaN1DPq4yffMAZ9czzBD)

  2. EVM-based H160 addresses:

    (e.g., 0x6B175474E89094C44Da98b954EedeAC495271d0F)

To streamline the process, we can break these problems down into smaller tasks and propose solutions for each, keeping the individual tasks manageable and focused.

Fragmentation problem

In the first part, we will focus on the fragmentation issue caused by SS58 prefixes.

Most Substrate-based chains use account systems compatible with this format, making it one of the biggest obstacles for users — even the ones building on Polkadot — to fully understand.

Why is the same underlying account represented with completely different address on each chain?

The SS58 format isn’t a “prefix” in the typical sense you would normally think about. It’s an address format that uses a prefix for the encoding function of the public key to generate a unique-looking address.

In most cases, addresses encoded with the same prefix will start with the same few letters. However, it doesn’t just change the first few characters — it alters the entire address. This causes confusion, especially compared to other ecosystems, where the same address can be reused across rollups or even solo chains.

While this system initially looks cool and promotes greater security, it becomes problematic when users want to use the same account across 50+ app chains. It creates friction when trying to build a seamless, familiar UX for users across the ecosystem.

The proposed solution is to unify the address format for all compatible chains within the Polkadot ecosystem. However, this comes with some implications that need to be addressed, and we’d like to discuss these with the broader community before moving forward with a formal proposal.

Wallets, dApps and informing users

There will be a transition period during which all wallet interfaces, dApps, and other platforms will need to be updated to inform users of the change.

We will create detailed guides to help developers ensure a seamless transition, along with resources to address the UX challenges. Additionally, we’ll provide explanatory documents and tools for users who may encounter issues during the transition.

Polkadot vault

Until recently, the go-to cold wallet provider used chain prefixes for account derivation and address display. We’ll need to guide users of older wallet versions to ensure a smooth transition during this change.

Exchanges

We generally see that CEXs are very rigid and resistant to change. This change subsequently worsens the issue of users sending funds to the wrong chain to on-ramp, because all of the address will look correct. One potential solution is to adopt address prefixes as suggested by EIP-3770, where the destination chain prefix is a human-readable short name, similar to the network field in our current SS58 registry. This will be discussed in more detail later in the proposal.

Fortunately, the reverse scenario — sending funds from a CEX to the wrong chain — typically doesn’t result in lost funds, as the accounts are interoperable between all of the compatible chains, but it still presents an UX issue. It will take time for CEXs to adapt to new address formats, and they may continue to require the old formats for withdrawals. To address this, wallet and dApp UIs will need to accommodate this by providing options to copy the appropriate address format.

Solving the fragmentation

We are proposing to use the following:

  1. Prefix:0 for compatible Polkadot parachains (usually starting with ‘1’)

    All compatible chains would use the same address format, allowing users to easily recognize their accounts across different chains, and eliminating the need for the SS58 registry in the current format. There is an ongoing referendum on Bifrost to adopt this prefix for their chain already.

  2. Prefix:42 - Substrate generic address format (usually starting with ‘5’)
    This prefix was supposed to be used by chains that don’t want to connect to Polkadot or Kusama relay-chains. Some wallets, like SubWallet and Talisman, already use this format by default to display all addresses. However, in the long run, chains that want to consider connecting to Polkadot or Kusama might want to use relay respective prefixes to prevent migration later on.

  3. Optional Kusama prefix discussion posted in separate thread

Other suggestions

If you have any alternative suggestions, we encourage you to share them in the discussion.

Sending funds to correct chain

As explained earlier, another part of the problem is identifying the destination chain for asset transfers to prevent mistakes. While this is usually not an issue within a single dApp, it becomes problematic in the context of app chains. One promising solution is using readable address prefixes, as outlined in EIP-3770.

We recognize that this is not fully compatible with Substrate-based addresses, as the proposal doesn’t support 32-byte addresses, let alone SS58 formatting. However, this doesn’t pose a significant risk to users. It means users won’t be able to send tokens to unsupported addresses in unsupported applications, which is generally better than risking the loss of funds.

The advantage of this approach is that it helps users understand that their address or account is the same across different chains. This pattern, while not yet fully accepted by Ethereum, is already implemented in various ecosystems and used by apps like Gnosis Safe.

Screenshot 2024-09-13 at 00.38.20

Summary

Together, these two proposals can significantly enhance the user experience within the Polkadot ecosystem. While they come with challenges, we will make sure all builders have the resources they need to make this transition as seamless as possible. We welcome any feedback on the proposal before posting it as a WFC (Wish for Change).

Note: This initiative serves as guidance only — chains and dApps are free to choose their own approach, as this is mostly a front-end matter of how account addresses are displayed. We highly recommend updating the on-chain SS58 prefix as this is the source of truth for many UIs and libraries and mismatch could potentially cause ledger and vault apps to stop showing correct address. We hope the benefits will be clear and that projects will come together to improve the overall UX in the ecosystem.

18 Likes

First and foremost, I want to emphasize that I fully share your concerns, and I am equally committed to finding a solution to the current situation. From the Polkadot-API team, we will be doing everything we can to contribute to this effort.

That being said, I believe there is one important detail that may have been overlooked: for this change to work effectively, all parachains using Substrate-based addresses should update the System.SS58Prefix constant in their respective runtimes to match the relay chain prefix (0 in the case of Polkadot).

This is important for a couple of reasons:

  1. Merkleized Metadata RFC-78: The value of this constant is part of the RFC-0078: Merkleized Metadata standard. As such, it is included in the merkleized root hash. If we suddenly switch to using a different SS58 prefix for address formatting, and that prefix doesn’t match what’s specified in the runtime, it will result in a mismatched root hash for extrinsics with the CheckMetadataHash mode enabled. This would cause those extrinsics to be deemed as invalid.

  2. Client Library Address Decoding: Client libraries, like PAPI (and perhaps also PJS and Subxt?), rely on the runtime constant value for decoding on-chain addresses. In PAPI, when we receive on-chain data identified as an Account32 address (inferred from the metadata), we respect the runtime constant value and format the address accordingly. This ensures consistency with what the chain has signaled through the runtime constant.

3 Likes

@josep I fully agree this change is not a trivial change, one of the things that we need to update as part of this change is changing SS58 prefix, specified in the runtime by the parachains. Some wallets and APIs use this value to convert the addresses, however this should really be a frontend change as the AccountId32 should be the decoded and compatible when doing any on-chain interaction. The chain should be ignoring the encoding. We don’t have this in the runtime really outside of the constant. The runtime receives the raw address AFAIK. There might be additional work required which should be highlighted by the team such as PAPI, and would be important for the execution of the proposal. This however should not be a blocker for agreeing on the proposal itself.

1 Like

First and foremost, I fully support the proposal. I want this change, and I strongly believe we should use the same format within the same consensus network. In fact, I would go a step further and advocate for using the same prefix across all Substrate-based chains.

Regarding PAPI, when encoding addresses, it accepts any SS58Address format and translates it into the public key required for chain interactions. So, for encoding addresses, we don’t rely on the System.SS58Prefix constant in the runtime.

However, when it comes to decoding on-chain data, specifically an “AccountId32”, we convert it into an SS58 string, and for this, we do need a prefix. By default, we use the prefix set on-chain (via the System.SS58Prefix constant). We could potentially stop doing that and adopt the relay chain’s prefix instead, but we need to proceed with caution. If we all start ignoring the on-chain SS58 prefix, the root-hash for transactions using the CheckMetadataHash signed extension wouldn’t match, leading to invalid extrinsics.

2 Likes

Can you elaborate on this point? Specifically, any example or hypothetical that comes to mind.

1 Like

Can you elaborate on how using the same prefix across all Substrate-based chains would alter the OP options? Is it a new option or a variation.

To avoid doubt, I take this to mean that, for example, the Aleph-Zero network “could” end up using the same prefixes as Polkadot and say, The Root Network, etc.

1 Like

Of course! Let’s take Hydration as an example. Currently, Hydration uses 63 as its System.SS58Prefix constant and supports the CheckMetadataHash signed extension.

So, the chain has computed its metadata merkelized root-hash using 63 as the SS58Prefix. Now, what would happen if DApps started ignoring Hydration’s actual prefix and used 0 instead (the relay chain’s prefix)?

Two potential outcomes:

  1. Mismatched Metadata Hash: If we sign a transaction with an offline device (like a Ledger) using 0 as the SS58Prefix, the transaction that the user sees on their device will match what the DApp displays. Naturally, the user would approve the transaction. However, since the CheckMetadataHash signed extension was computed using 63 (Hydration’s SS58 prefix), the hash won’t match what’s on-chain, causing the extrinsic to be invalid.

  2. User Confusion with Address Mismatch: If we use the actual on-chain SS58Prefix (63) only for the offline device, the addresses shown on the user’s offline device during transaction signing will differ from what the DApp is showing. This can cause users to panic and reject the transaction. Imagine you want to send funds to 15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5, but your ledger device displays the recipient as 7NPoMQbiA6trJKkjB35uk96MeJD4PGWkLQLH7k7hXEkZpiba—many users would not approve that transaction. Even if they did, that would be a horrendous UX.

In essence, for this change to be effective and avoid these issues, all chains should align their SS58Prefix with the relay chain they are connected to.

4 Likes

I really don’t want to hijack this conversation, so I won’t elaborate on this. All I’m saying is that I wish that we had 1 universal format for displaying 32-byte public keys. IMHO that would make things much simpler. However, that’s way out of the scope of this conversation, and it’s probably not really feasible to do that at this point. I said that to signal @jak-pan that we share the same goals and concerns.

1 Like

@josep Yes, I agree, chains need to update their SS58Prefix if they want to make this change, this is supposed to be a part of the guides once we align on this as stated in the proposal, there are multiple things we will need to solve and we understand this specific problem. One of the biggest and most important ones are hardware wallets and CEXs but everything is solvable and pretty trivial compared to ecosystem confusion we are experiencing right now.

3 Likes

Fully support this proposal, and Bifrost is also trying it out according to its own ideas. At present, we prefer to use prfix:0 as the display format for any parachians. We hope to understand the potential negative effects of this treatment (please let me know if there are any). :saluting_face:

2 Likes

Thank you very much for your professional advice. Our current plan is to prioritize complete UX changes without changing the information on the chain. We want to understand the potential risks and adverse experiences that will be caused by doing so (without updating the Runtime). We need to evaluate this impact and decide whether to update it in the next update of Bifrost. (In addition, will updating the System.SS58Prefix constant affect other logic on the chain? Or is this just an independent factor?)

1 Like

Thanks, that was largely my understanding. I’m mostly curious about how the Prefix:42 - Substrate generic address format (usually starting with ‘5’) option opens the door to chains using “… their prefixes to prevent migration later on.”

1 Like

I strongly advise against this approach. Modifying the user experience without updating the corresponding on-chain data -specifically, the System.SS58Prefix constant- can lead to significant issues. The System.SS58Prefix is the actual trustless source that signals to tools and DApps how to correctly format addresses for your chain. Ignoring this can result in inconsistencies, user confusion, and potentially invalid transactions.

If you intend to change the SS58 prefix of your chain, it’s essential to update the runtime constant accordingly. This ensures that all tools and DApps can accurately format addresses and interact with your chain as expected.

If you’re considering a gradual transition to prepare your users for the upcoming change, that makes sense. Implementing features like tooltips or notifications in your dApps to inform users about the future address format can help ease the transition. However, it’s crucial not to promote the idea that generic tools and DApps should ignore the on-chain SS58 prefix, as this could lead to broader compatibility issues.

I’ve outlined some of the potential risks in my previous comments. Ignoring the on-chain SS58 prefix can cause mismatches in address formatting, leading to user confusion, failed transactions, and incompatibility with existing tools and DApps. For instance, transactions may fail validation if the CheckMetadataHash signed extension detects discrepancies between expected and actual metadata. I recommend testing these scenarios in a local environment or on test networks to fully understand the implications before proceeding.

Since it’s “your” chain, you and your development team are best positioned to answer this thoroughly. Generally speaking, unless you’ve implemented custom logic that depends on the System.SS58Prefix constant, updating it should primarily affect address formatting and the computation of the merkleized metadata hash - particularly for transactions using the CheckMetadataHash signed extension. It shouldn’t impact other on-chain logic.

3 Likes

I think this was misunderstood… I suggested chains wanting to connect to the Relay-chains or the ecosystem in other ways should use the respective Relaychian prefix to avoid migrating addresses later on.

1 Like

This doesn’t affect any runtime logic. (unless there is special custom logic handling SS58 which I think 99.9% of chains don’t do) But it can affect Polkadot vault and Ledger in a sense that when the front end mismatches the runtime constant it will show you wrong address format for the destination accounts. This is currently the case also when sending transactions cross-chain that should be fixed by unifying the address formats.

2 Likes

I think data representation should not be the users main concern. A resolver providing unified names and resolving underneath to the respective SS58 / H160 representation would be the easiest for the typical literate user.

A resolver like this would also open up a unified dns like system based on utf-8 / utf-16 and could be a combination of a web service and some authority pallet magic, e.g. on people chain, where from gut feeling this would be a great fit.

1 Like

This would be beautiful addition on top of anything we have, but it’s not really part of this proposal and doesn’t solve our underlying problems at this moment. However this will be important in the future for pushing the UX even further it’s still much farther away than we would like it to be.

2 Likes

This will significantly improve both UX and security by helping users distinguish legitimate addresses from fraudulent ones. As a result, transaction validations become more accurate and user-friendly, enabling more efficient defense against growing sophisticated threats like clipper malware, as recently highlighted by Binance. Additionally, it simplifies managing whitelisted or trusted beneficiary addresses (and their associated human readable descriptions) when a transaction validation protocol is in place, offering users a streamlined and more secure experience.

1 Like

What about just using the public key

  • 4fYrN4QvRaBf6HpWShZnFR7hNsGSEBHDw1115jYQqQE5SkTL on Centrifuge → becomes 0xba2c4540acac96a93e611ec4258ce05338434f12107d35f29783bbd2477dd20e
  • 15D74LvQb6hVUBFoqXtveyYQ7Q7rFacV994Gw8PaAcpXKB2L on Polkadot → becomes 0xba2c4540acac96a93e611ec4258ce05338434f12107d35f29783bbd2477dd20e
2 Likes

I was actually considering proposing this, however it might bring more problems.

  1. Address in this format is similar to ETH addresses, but it’s not compatible.
  2. It’s very long and I would argue harder to check for mistakes, with prefix it becomes super long.
  3. The proposed change is kind of compatible with all the current UIs but the pubkey would most probably be a breaking change for everybody.
  4. Ledger app / Merkelized metadata would need a change.

I don’t see any other super big immediate problems with this, but there might be something else. @joepetrowski @josep do you find using pubkeys plausible? ( I am personally still on the side of just changing the prefix because of the above )

1 Like