Skip to content
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
Cannot retrieve contributors at this time


CAP: 0027
Title: First-class multiplexed accounts
Author: David Mazières and Tomer Weller
Status: Final
Created: 2019-12-05
Protocol version: 13

Simple Summary

A new type of Account ID includes a 64-bit memo ID. This memo ID has no effect on the semantics of operations or their authorization, but it facilitates multiplexing a single account across multiple users.


A common pattern in the Stellar ecosystem is for services to share a single Stellar account ID across many users, relying on the memo ID to disambiguate incoming payments.

Experience shows that people frequently forget to include the memo ID, resulting in either lost funds or onerous support calls. Moreover, memo IDs are per transaction, not per occurrence of an account ID, which imposes restrictions on the use of multiplexed accounts. For example, it is not possible to include multiple payments to different multiplexed accounts in the same transaction. Similarly, it is not possible to refund payments from a multiplexed account ID, as the transaction's memo ID by convention describes only the destination, not the source of funds.

By adding an optional memo ID to the account ID type, we make multiplexed accounts a first-class abstraction that can be used anywhere a normal account ID can be used.

Goals Alignment

First-class multiplexed accounts help scalability by eliminating an incentive for users to create many accounts when virtual accounts would suffice. They also significantly improve usability by addressing the pain point of support costs for users who forget memo IDs.


A new type, MuxedAccount, replaces AccountID in many places. A MuxedAccount can contain either a plain Ed25519 public key, or a public key and a 64-bit subaccount ID. The subaccount ID has no effect on the semantics of transactions, but can be used by higher-layer software to multiplex a single stellar account among multiple users.


The multiplexed account type is represented by a new XDR union:

enum CryptoKeyType
    KEY_TYPE_ED25519 = 0,
    KEY_TYPE_MUXED_ED25519 = 256,  // This is new

// Source or destination of a payment operation
union MuxedAccount switch (CryptoKeyType type) {
 case KEY_TYPE_ED25519:
     uint256 ed25519;
 case KEY_TYPE_MUXED_ED25519:
     struct {
         uint64 id;
         uint256 ed25519;
     } med25519;

The following fields, which were previously an AccountID or AccountID*, are now a MuxedAccount or MuxedAccount* (respectively):

  • PaymentOp::destination
  • PathPaymentStrictReceiveOp::destination
  • PathPaymentStrictSendOp::destination
  • Operation::sourceAccount
  • Operation::destination (for ACCOUNT_MERGE)
  • Transaction::sourceAccount
  • FeeBumpTransaction::feeSource

Note, however, that this must not be implemented before CAP-0015 or CAP-0019 (which updates the transaction format), as these other CAPs depend on all existing transactions starting with 4 zero bytes (which will no longer be the case when the transaction's sourceAccount is a MuxedAccount).

Design Rationale

A previous ecosystem-only proposal had too many limitations, including the inability to send payments to several virtual accounts, the inability to specify virtual accounts as a source, and increased cognitive load for developers. The CAP approach seems cleaner, with very little added complexity in the server.

The particular set of fields promoted to MuxedAccount were chosen to avoid any changes to the database. Hence, assets and offers are still associated with an AccountID rather than a MuxedAccount.

As for the strkey update, there were 3 unused bits at the bottom of each version byte that do not affect the first character, so we decided to reserve these to facilitate future crypto agility. A different letter was chosen for multiplexed accounts because these are not completely interchangable with traditional AccountID values. (For instance, a multiplexed account cannot issue assets, only the base account can do so.)

Backwards Incompatibilities

All existing transactions will continue to be valid, but transactions with a MuxedAccount will not be parsable by old software. Hence, the best time to roll out this change will be at the same time as CAP-0015. Software that converts new-style transactions to old can also strip out the identifiers from MuxedAccount structures.

Security Concerns

Certain addresses that are identical may not look identical. This could confuse client software. For instance, sending an asset to a multiplexed account tied to the issuer will destroy the asset.

Code that uses a denylist to block specific accounts from receiving AUTH\_REQUIRED assets will need to ensure that multiplexed accounts cannot be used to bypass the denylist. This is not an issue for non-AUTH\_REQUIRED assets, as anyone can already evade such denylists by creating new accounts. There is no issue for allowlists, since failure to accommodate multiplexed accounts just prohibits people from using them, preserving the status quo ante.

People commonly assume that base-32 decoding libraries will reject inputs with invalid lengths or invalid trailing bits, but this is often not the case, particularly when padding is disabled. If implementations forget to check this, they will parse invalid strkeys. This could lead to problems, particularly if strkeys are used as indexes in a hash table, where an attacker could create multiple entries for the same account.


An implementation can be fetched to FETCH_HEAD with the following command:

git fetch dm/muxacct

The github web page associated with that branch is here: