How can I split a value received by the contract and transfer the split amount to another wallet?

I have this script:

script;

use std::logging::log;
use std::asset::transfer;

abi MyContract {
    #[payable]
    fn transfer();
}

configurable {
    CONTRACT_ADDRESS: b256 = b256::zero(),
    FEE_RECEIVER: b256 = b256::zero(),
}

fn main(amount: u64, default_asset_id: AssetId) {
    let asset_id = AssetId::new(ContractId::from(CONTRACT_ADDRESS), SubId::zero());
    
    // Call the contract to receive the minted asset
    let my_contract = abi(MyContract, CONTRACT_ADDRESS);
    my_contract.transfer{
        asset_id: default_asset_id.into(), coins: amount
    }();

    // Calculate the fee
    let fee = amount * 2 / 100;

    // Transfer the fee to the fee receiver
    transfer(Identity::Address(Address::from(FEE_RECEIVER)), asset_id, fee);
}

  1. The account calls the method to receive another asset
  2. The user receives the same amount of coins sent
  3. In the final step, the fee is calculated and sent to the fee receiver.

I’m calling this script in TS and getting the following error:
FuelError: The transaction reverted with reason: “NotEnoughBalance”.

const script = new ExampleScript(wallet!);
script.setConfigurableConstants({
    CONTRACT_ADDRESS: contract.id.toB256(),
    FEE_RECEIVER: receiver!.address.toB256(),
});

try {
    const baseAssetId = await contract.provider.getBaseAssetId();
    const response = await script.functions
        .main(1000, {bits: baseAssetId})
        .addContracts([contract])
        .txParams({
            variableOutputs: 2,
        })
        .call();
    const result = await response.waitForResult();
    console.log("Success", result.logs);
} catch (error) {
    console.log(error.metadata.logs.map(l => l.format?.()));
}

If I remove the fee transfer from the script, the method executes successfully.

Why does this error occur? Is it possible to do this?
Just to give some context on what I’m trying to do: in my application, every time this script is executed, I need to split the protocol fee.

@luisburigo As i can see here, you are transferring an amount to the contract and then a part of the it as a fee to the fee receiver. Though, you are using two different AssetIds here.

firstly, you are generating an assetId here, that you are using to transfer the fee.

Secondly, you are using the defaultAssetId() in your ts sdk as well as while transferring minted assets to the contract.

both these assetIds are different and might be an issue. please try this below contract and see if the error still exists

script;

use std::logging::log;use std::asset::transfer;

abi MyContract {
#[payable]
fn transfer();
}

configurable {
CONTRACT_ADDRESS: b256 = b256::zero(),
FEE_RECEIVER: b256 = b256::zero(),
}

fn main(amount: u64, default_asset_id: AssetId) {
// Call the contract to receive the minted asset
let my_contract = abi(MyContract, CONTRACT_ADDRESS);

my_contract.transfer{asset_id: default_asset_id.into(), coins: amount}();

// Calculate the fee
let fee = amount * 2 / 100;

// Transfer the fee to the fee receiver using the same asset
transfer(Identity::Address(Address::from(FEE_RECEIVER)), default_asset_id, fee);

}