Symbol: possible converting account without funds to multisig?

I’m developing a service backed by Symbol, for which I want to setup a user’s accounts. The Symbol accounts are setup by the service, and so the service has access to the private keys of the accounts at the time of the setup. The accounts involved are:

  • SD_msigAccount is the account that needs to be converted to a multisig account to be used by the user
  • SD_cosign1Account and SD_cosign2Account are the user-controlled accounts to be configured as cosignatories
  • serviceAccount and serviceCosignAccount are accounts used by the service provider, and will also be set as cosignatories.

The service can operate correctly without any XYMs in the users accounts. So I would like to convert the user’s account SD_msigAccount to multisig and pay the fees from the serviceAccount.

I’m trying implementing it this way:

  • make SD_msigAccount sign the MultisigAccountModificationTransaction
  • create the hashlock transaction with the serviceAccount
    as shown below, but this still requires the SD_msigAccount to pay transaction fees.

Is what I’m trying to achieve possible? If yes how?

    const multisigAccountModificationTransaction = MultisigAccountModificationTransaction.create(
        Deadline.create(epochAdjustment),
        3, // minApprovalDelta
        3, // minRemovalDelta
        [SD_cosign1Account.address,
         SD_cosign2Account.address,·
         serviceCosignAccount.address,·
         serviceAccount.address], // address additions
        [], // address deletions
        networkType,
    );
    const aggregateTransaction = AggregateTransaction.createBonded(
        Deadline.create(epochAdjustment),
        [multisigAccountModificationTransaction.toAggregate(SD_msigAccount.publicAccount)],
        networkType,
        [], // cosignatures
        UInt64.fromUint(2000000), //maxFee
    );
    const signedTransaction = SD_msigAccount.sign(
      aggregateTransaction,
      networkGenerationHash,
    );
    // lock 10 xym as spam prevention
    const signedHashLockTransaction = await createSignedHashLockTx(signedTransaction,serviceAccount)

If you include a simple transfer transaction from serviceAccount to SD_msigAccount as a component tx in the aggregate tx, your effectively giving SD_msigAccount the xym required to pay the fee in the process of setting up the multisig account. If the multisig account creation fails, so will the transaction that funds the transaction cost.

I wanted to avoid this because it seems hard to know the transaction costs that need to be covered. If I transfer too much, some funds will stay in SD_msigAccount, and it is possible a small amount impossible to transfer back due to fees being bigger, eg 0.1 XYMs. If many such accounts are created, it can become a rather big amount lost. Can it be avoided?

This shouldn’t happen i don’t think. What you would do is set the fee of the transaction your paying for equal to that of the amount being transferred to the account. This way, if the aggregated transactions are all accepted, this would mean 100% of the xym you transferred would go to the harvester in the form of transaction fee and not leave any dust behind. Since it is atomic, if the transaction incurring the fee is not processed, the transaction funding the fee won’t be processed either. The only reason dust would be left behind is if you set the fee different to that of the amount being transferred to cover the fee but this shouldn’t happen if you calculate it in advance. Which bit of the fee calculation isn’t clear or do you feel can’t be calculated in advance?

On the testnet I set a max fee to 2000000, and it was often smaller.
Here is a metadata transaction for which I set the max_fee to 2000000, but it was effectively 1999840.
I must say I didn’t take a close look to the fee calculations, being on the testnet. If you have some advice about it , I’m interested!

Using an AggregateComplete achieves what I want, thx for the suggestion @kodtycoon !

No problem. :slight_smile: