Skip to content

Add Native SAC mint capabilities in tests #1854

@teddav

Description

@teddav

What problem does your feature solve?

Working with native tokens (XLM) in unit tests is unnecessarily complicated, and CAP-73 now lets contracts create G-accounts, but testing that flow requires funding those accounts with native tokens, something the SDK doesn't directly support.

There are two specific gaps.

1. No straightforward way to obtain the native SAC.

I work around it like this:

fn register_native_sac(env: &Env) -> Address {
    let asset = Bytes::from_slice(env, &[0, 0, 0, 0]);
    env.deployer().with_stellar_asset(asset).deploy()
}

@aolieman uses a similar approach.

But even once you have the SAC, there's no way to mint into it.

2. No way to fund G-accounts.

For C-addresses, Address::generate() from testutils works fine. For G-accounts, the only path I've found is to manually construct a ledger entry and inject it via the host:

fn generate_funded_g_account(env: &Env, stroops: i64) -> Address {
    let pk: [u8; 32] = BytesN::<32>::random(env).to_array();
    let account_id = xdr::AccountId(xdr::PublicKey::PublicKeyTypeEd25519(xdr::Uint256(pk)));
    let key = Rc::new(xdr::LedgerKey::Account(xdr::LedgerKeyAccount {
        account_id: account_id.clone(),
    }));
    let entry = Rc::new(xdr::LedgerEntry {
        data: xdr::LedgerEntryData::Account(xdr::AccountEntry {
            account_id: account_id.clone(),
            balance: stroops,
            flags: 0,
            home_domain: Default::default(),
            inflation_dest: None,
            num_sub_entries: 0,
            seq_num: xdr::SequenceNumber(0),
            thresholds: xdr::Thresholds([1; 4]),
            signers: xdr::VecM::default(),
            ext: xdr::AccountEntryExt::V0,
        }),
        last_modified_ledger_seq: 0,
        ext: xdr::LedgerEntryExt::V0,
    });
    env.host().add_ledger_entry(&key, &entry, None).unwrap();
    Address::try_from_val(env, &xdr::ScAddress::Account(account_id)).unwrap()
}

This depends on internal host APIs and a lot of XDR boilerplate. Again, @aolieman has similar workaround code.
Multiple users converging on the same hacks suggests this belongs in testutils.

What would you like to see?

Two additions to testutils:

  1. A helper to obtain the native SAC, e.g. env.native_asset_contract() or an equivalent on Env/StellarAssetContract.
  2. A way to mint native tokens in tests, either by exposing admin capabilities on the native SAC, or via a dedicated env.fund_account(address, stroops) helper that works for both G- and C-addresses.

Together these would make CAP-73 end-to-end testable: contracts that create and fund G-accounts could be exercised in unit tests without resorting to host-level ledger entry injection.

As a related note (probably worth a separate issue): distinguishing C-addresses from G-addresses given an Address is also harder than it should be (both in test and also in contract code). A built-in way to check the address type would pair well with the helpers above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions