Unexpected behavior when callings scripts

Hey guys, now that I can call a script, I get multiple unexpected behavior. Thus, I reduced my complex script to a simple script to test. Assume my wallet on the TS SDK side is funded by more than enough tokens. My simple script looks like this:

fn main(
    some_contract: ContractId,
) {
    transfer(1_000_000, BASE_ASSET_ID, Identity::ContractId(some_contract));

My script call looks like this (in the TS SDK):

const scriptInstance = new Script<ContractIdInput[], any>(scriptBin, simpleScriptAbi, wallet);
const value = await scriptInstance.functions
        .main({ value: someContract.id.toHexString() })
        .txParams({ gasPrice: 1 })
                id: someContract.id,
                account: someContract.account,
                interface: {
                    encodeFunctionData: someContract.interface.decodeFunctionData,
                    decodeFunctionResult: someContract.interface.decodeFunctionResult,
                    updateExternalLoggedTypes: someContract.interface.updateExternalLoggedTypes,
                    loggedTypes: someContract.interface.loggedTypes,
                provider: someContract.provider,

It just transfers an amount of the BASE_ASSET_ID to my contract some_contract . This works and I can prove that the BASE_ASSET_ID flows from my wallet to the contract by querying the balances on the TS SDK side. Now comes the trouble. As soon as I want to transfer my own token instead of the BASE_ASSET_ID, the script receipt says “NotEnoughBalance”. Again, I can prove that there is enough balance. What can be the reason? Another weird thing is that I cannot query the balance of my contract inside my script. If instead of calling the transfer function, I call the stdlib balance_of function and give it my contract id and BASE_ASSET_ID , the script receipt says ContractNotInInputs . I was not aware, that the base asset even has a contract that I could put into the inputs??? Any answer would be very welcome, this is completely blocking our development.

Oh in case somebody wonders why I would add .addContracts() when calling the script even though I don’t use the contract abi inside the script… well, I don’t know why it’s required but if I don’t add it in the call, I get a ContractNotInInputs script panic.

When running a script, you need to manually collect the UTXOs you want the script to have access to, and pass those UTXOs to the script when it’s called.

You can see the code for gathering UTXOs in the AMM example:

Although this is written in Rust, so something similar would have to be done in TypeScript.

Regarding calling .addContract(), you need to append a contract UTXO to a transaction in order to have access to that contract’s balance, even if you’re not directly calling the contract.