How to receive tokens and use them in the same script code?

I have a script that successfully does a swap, but when i try to use the received tokens I get a NotEnoughBalance Panic error.

I noticed that the scripts address is represented as zero address (0x00) in the logs and receipts, so I have tried using 0x00 instead of my EOA address, but it seems that the script fails regardless…I’m not able to have Mira send the tokens directly to the next destination in this context.

Do i have to do something special to receive tokens and use it within the same script code?

Here are some relevant receipts, showing the initial swap:

Transfer {
                id: 0x0000000000000000000000000000000000000000000000000000000000000000,
                to: 0x2e40f2b244b98ed6b8204b3de0156c6961f98525c8162f80162fcf53eebd90e7,
                amount: 1830266234186,
                asset_id: 0x1d5d97005e41cae2187a895fd8eab0506111e0e2f3331cd3912c15c24e3c1d82,
            },
TransferOut {
                id: 0x2e40f2b244b98ed6b8204b3de0156c6961f98525c8162f80162fcf53eebd90e7,
                to: 0xMyEoaAddress,
                amount: 52540645,
                asset_id: 0x286c479da40dc953bddc3bb4c453b608bba2e0ac483b077bd475174115395e6b,
            },
Panic {
                id: 0x0000000000000000000000000000000000000000000000000000000000000000,
                reason: PanicInstruction {
                    reason: NotEnoughBalance,
                    instruction: CALL { target_struct: 0x10, fwd_coins: 0x18, asset_id_addr: 0x17, fwd_gas: 0x16 } (bytes: 2d 41 85 d6),
                },
                pc: 28972,
                is: 10368,
                contract_id: None,
            },
2 Likes

Could you please share a code snippet for me to look at?

1 Like

Sure. Here is the segment of the script that is being run. The swap is successful, and the Panic is when it tries to deposit into Spark.


                // swap
                amm.swap(
                        pool_id, 
                        amounts_out_min_0.get(cur_index).unwrap(), 
                        amounts_out_min_1.get(cur_index).unwrap(), 
                        to, 
                        Bytes::new()
                );

                // don't do any further actions if this is the last swap
                if is_last_swap {
                    continue;
                }

                // exit early if mira is next swap
                if to == Identity::ContractId(AMM_CONTRACT_ID) {
                    continue;
                }

                // get amount out and deposit it into spark
                let amount_out = if pool_id.0 == path.get(cur_index).unwrap() {
                    amounts_out_min_1.get(cur_index).unwrap()
                } else {
                    amounts_out_min_0.get(cur_index).unwrap() 
                };

                log(Debug { amount_out });

                // i is already incremented, so this is the next token in the path
                let token_out = path.get(i).unwrap();
                log(DebugAsset { asset: token_out });

                // deposit into spark
                let spark = abi(SparkMarket, next_spark_pool.into());
                spark.deposit {
                        asset_id: token_out.into(),
                        coins: amount_out,
                }();

The logs show that I am using the correct assetId and amount out.
I have tried running it with to = my eoa address and also with to = 0x0. Both result in the same error. The script works when there are multiple Mira pools to be swapped on, but in that case the assets aren’t actually leaving the Mira pool.

Here is the Rust SDK code to call the script:

    let script = get_swap_script_instance(wallet_local)?;
    let mira_amm = mira::Mira::new(*mira::AMM_CONTRACT, wallet_local.clone());
    let helper = mira::Mira::new(*mira::SWAP_INPUT_CONTRACT, wallet_local.clone());
    let tx_policies = TxPolicies::default().with_script_gas_limit(GENERAL_SWAP_GAS_LIMIT);

    let (inputs, outputs) = mira::get_transaction_inputs_outputs(
        &wallet_local,
        &[(path[0], amount_in)],
        GENERAL_SWAP_GAS_LIMIT,
    )
    .await?;

    // TODO: build all from 'spark_contracts'
    let mut contract_dependencies = pools
        .iter()
        .filter(|p| match p {
            DexSwap::Spark(_) => true,
            _ => false,
        })
        .map(|p| match p {
            DexSwap::Spark(x) => spark::SparkOrderbook::new(x.contract_id, wallet_local.clone()),
            _ => panic!("porqueeee"),
        })
        .collect::<Vec<spark::SparkOrderbook<WalletUnlocked>>>();

    contract_dependencies.extend(
        spark_contracts
            .iter()
            .map(|s| spark::SparkOrderbook::new(s.1, wallet_local.clone()))
            .collect::<Vec<spark::SparkOrderbook<WalletUnlocked>>>(),
    );

    let mut call = script
        .main(
            amount_in,
            amount_out_min,
            pools,
            path,
            amounts_out_min_0,
            amounts_out_min_1,
            recipient.into(),
            deadline,
        )
        .with_tx_policies(tx_policies)
        .with_contracts(
            contract_dependencies
                .iter()
                .map(|contract| contract as &dyn ContractDependency)
                .chain([
                    &mira_amm as &dyn ContractDependency,
                    &helper as &dyn ContractDependency,
                ])
                .collect::<Vec<&dyn ContractDependency>>()
                .as_slice(),
        )
        .with_inputs(inputs)
        .with_outputs(outputs)
        .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum);

    match call.simulate(Execution::Realistic).await {
        Ok(tx) => {
            dbg!(tx);
        }
        Err(e) => {
            dbg!(e);
        }
    }

Hey!

I’ll check with the team and get back to you shortly. Stay tuned!

4 Likes

hey @fuel any word?
i mostly would like to know if this is even possible or if I am 100% doing something wrong.

1 Like

@naz3eh @fuel @Rubyto is there anybody who can help me with this?