CAP: 0079
Title: Host functions for muxed address strkey conversions
Working Group:
Owner: Dmytro Kozhevin <@dmkozh>
Authors: Dmytro Kozhevin <@dmkozh>
Consulted:
Status: Implemented
Created: 2026-01-13
Discussion: https://github.com/orgs/stellar/discussions/1840
Protocol version: 26
Introduce host functions for converting Stellar strkey format strings to/from Address/MuxedAddress objects.
As specified in the Preamble.
Stellar protocol provides host functions for converting the account and contract Stellar SEP-23 strkeys to/from the corresponding AddressObject. In protocol 23 a new MuxedAddressObject type has been added for supporting muxed account addresses (CAP-67). However, the corresponding strkey conversion functions haven't been added.
The use case for the missing conversions is the same as for the original strkey conversion functions: unlike Stellar smart contract specific ScVal/ScAddress XDR types, strkeys provide a portable and user-friendly way of supporting Stellar addresses on other chains. That's preferred way for cross-chain protocols (such as bridges) to communicate with the Stellar chain. Muxed address support is necessary to allow these protocols to easily send tokens to muxed destinations across chains.
This CAP is aligned with the following Stellar Network Goals:
- The Stellar Network should make it easy for developers of Stellar projects to create highly usable products
New host functions strkey_to_muxed_address and muxed_address_to_strkey for performing the conversions. These functions are similar to the existing strkey_to_address/address_to_strkey, but they can have a MuxedAddressObject as an output or input respectively.
The diff is based on commit 30ab5d1e2a642f18f3ae94cdb3a2798c3123f049 of rs-soroban-env.
diff --git a/soroban-env-common/env.json b/soroban-env-common/env.json
index 945ada2c..b8d76d4d 100644
--- a/soroban-env-common/env.json
+++ b/soroban-env-common/env.json
@@ -2534,6 +2534,32 @@
"return": "Val",
"docs": "Returns the executable corresponding to the provided address. When the address does not exist on-chain, returns `Void` value. When it does exist, returns a value of `AddressExecutable` contract type. It is an enum with `Wasm` value and the corresponding Wasm hash for the Wasm contracts, `StellarAsset` value for Stellar Asset contract instances, and `Account` value for the 'classic' (G-) accounts.",
"min_supported_protocol": 23
+ },
+ {
+ "export": "7",
+ "name": "strkey_to_muxed_address",
+ "args": [
+ {
+ "name": "strkey",
+ "type": "Val"
+ }
+ ],
+ "return": "Val",
+ "docs": "Converts a provided Stellar strkey address of an account, muxed account, or a contract ('G...', 'M...' or 'C...' key respectively) to an AddressObject or MuxedAddressObject (for 'M...' keys). `strkey` can be either `BytesObject` or `StringObject` (the contents should represent the base32 strkey in both cases). Any other valid or invalid strkey (e.g. 'S...') will trigger an error. Prefer directly using the Address objects whenever possible. This is only useful in the context of custom messaging protocols (e.g. cross-chain).",
+ "min_supported_protocol": 26
+ },
+ {
+ "export": "8",
+ "name": "muxed_address_to_strkey",
+ "args": [
+ {
+ "name": "address",
+ "type": "Val"
+ }
+ ],
+ "return": "StringObject",
+ "docs": "Converts a provided AddressObject or MuxedAddressObject to Stellar strkey format ('G...' for account, 'M...' for muxed account, or 'C...' for contract). Prefer directly using the Address objects whenever possible. This is only useful in the context of custom messaging protocols (e.g. cross-chain).",
+ "min_supported_protocol": 26
}
]
},muxed_address_to_strkey accepts a single Val argument that can be either AddressObject, or MuxedAddressObject. AddressObject will be converted to an account (G...) or contract (C...) strkey corresponding to the address. MuxedAddressObject will be converted to a muxed account strkey (M...).
The function traps if a Val of invalid type is provided.
strkey_to_muxed_address accepts a single Val containing strkey in BytesObject or StringObject.
Valid G... and C... strkeys will be converted to corresponding AddressObject. Valid M... strkeys will be converted to corresponding MuxedAddressObject.
The function traps if a Val of invalid type is provided, or if the input doesn't contain a valid strkey of one of the 3 types specified above.
There is a potential possibility of updating the interface of the existing host functions instead of introducing new ones.
For strkey_to_address if M... strkey is passed, the contract would fail inside the host function in the older protocols, and fail when trying to interpret the return value as AddressObject in the new protocol. Both would result in the contract trapping.
For address_to_strkey MuxedAddressObject generally wouldn't be passed, so the function behavior would remain the same.
Even though the change seems safe for the base scenarios, there may be more subtle dependencies for the implementation of the existing functions (e.g. if a polymorphic Val is expected/used), and thus we err on the side of caution here and leave the semantics of the existing functions as is.
The SDKs may just switch to v2 functions unconditionally for the future contracts.
This CAP does not introduce any backward incompatibilities. The existing strkey conversion functions will still be supported as is.
The new host functions will be metered in the same fashion as the existing strkey conversion functions. The metering can rely on the existing cost types and does not require additional benchmarking and calibration.
This doesn't introduce any new risks.
TBD
TBD