Skip to content

Support muxed (M…) source accounts in the contract invoke pipeline #2645

Description

@fnando

Background

Spun out of review feedback on #2644 (stellar token transfer). SEP-41 supports muxed addresses (CAP-67 ScAddress::MuxedAccount), and --from M… almost works today: UnresolvedMuxedAccount resolves it, and arg parsing + simulation accept it.

Problem

It then fails in the shared contract invoke pipeline at cmd/soroban-cli/src/commands/contract/invoke.rs:349:

client.get_account(&config.source_account()?.to_string()).await?

The M… strkey is handed to a G-only ed25519 parser, aborting with a raw strkey DecodeError. Because this lives in the shared pipeline, contract invoke --source-account M… hits the same failure — it is not specific to token transfer.

Direction

stellar-xdr already provides xdr::MuxedAccount::account_id(). The pipeline should use the underlying AccountId (e.g. config.source_account()?.account_id().to_string()) for the sequence-number lookup and the classic transaction source in build_invoke_contract_tx, while the muxed form keeps flowing into the SEP-41 transfer(from, …) argument so the mux id is preserved on-chain / in events.

Acceptance

  • --source-account M… / --from M… works end-to-end through simulate → sign → submit.
  • Add an integration test with an M… source (signing via an identity / --sign-with-*, since an M-literal carries no secret).

Notes

Pre-existing limitation, not a regression from #2644. Until this lands, token transfer may want a clear "muxed source not yet supported" guard error instead of the raw DecodeError.

Part of the "Improve Agent UX for Wallets" epic (#2620).

Activity

  1. moved this to Backlog (Not Ready) in DevXon Jul 14, 2026
  2. added a commit that references this issue on Sep 1, 2026
    70f6642
  3. Galmanus commented on Sep 1, 2026

    @Galmanus

    @fnando quick design question before #2694 gets a review pass, since it deviates from the Direction here on one point and I'd rather settle it in the issue than in review.

    The Direction says the muxed form should keep flowing into the SEP-41 transfer(from, …) argument so the mux id is preserved. Empirically that path fails: on a protocol-27 quickstart, a muxed from fails simulation with HostError: Error(Value, UnexpectedType) — consistent with muxed addresses not being accepted by require_auth (the same ruling #2534 encodes for auth entries). So #2694 currently resolves a muxed --from to the underlying G… for the transfer argument, while a muxed --to still flows through as-is and keeps the mux id in the argument and events.

    Two ways to go:

    1. Keep the resolution as in feat: support muxed (M…) source accounts in the contract invoke pipeline #2694: muxed --from works end-to-end, mux id preserved on the --to side only.
    2. If there is a supported way to carry the mux id on the authorized from side that I missed in CAP-67 / the host, I'll rework the PR to that shape.

    Happy either way — mostly want the direction confirmed before review time is spent on the wrong shape.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      Backlog (Not Ready)

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions