When predicates release funds to a specified contract addr, the balance doesn't reflect in the contract, or via the providers in the rust sdk

When I specified a normal eoa wallet address(via the transaction inputs and outputs), the funds are sent from the predicate to the addresss and it shows, but doesn’t reflect for a contract address, why is this so, if i am not making a mistake can someone show me how to properly specify that funds should be sent to a contract from a predicate if it evaluates to true.

please urgent !

*This is how i specified the inputs and outputs of the transaction

   let mut inputs = vec![Input::Contract {
            utxo_id: UtxoId::new(Bytes32::zeroed(), 0),
            balance_root: Bytes32::zeroed(),
            state_root: Bytes32::zeroed(),
            tx_pointer: TxPointer::default(),
            contract_id: flash_sync.flash_vault_contract_id,
        }];


          let inputs1 = predicate
                                       .get_asset_inputs_for_amount(
                                        *base_asset_id, 
                                        4_000_000, 
                                        None
                                    ).await.unwrap();
                                    println!("inputs {:#?}", inputs.clone());
                                    inputs.extend(inputs1);

          let outputs = vec![
            Output::Coin {  
                to : Address::new(*vault_id),
                amount: 4_000_000,
                asset_id: *base_asset_id,
            },
                Output::contract(0, Bytes32::zeroed(), Bytes32::zeroed())  ,
                Output::Change {
                    to: predicate.clone().address().into(),
                    amount: 0,
                    asset_id: *base_asset_id,
                }

        ];

however the vault doesn’t reflect the amount sent to it, but the predicate balance is reduced base on how much was requested out of it.

but if you specify the funds be sent to a normal address, the address reflects the balance sent to it

Hey @shealtielanz, are you trying to transfer funds to a contract using a normal UTXO output?

Smart contracts can’t “receive” UTXOs, funds must be transferred to smart contracts using smart contract “calls”.

If you want your predicate to enforce that some funds are transferred to a smart contract, you will have to have your predicate enforce the transaction script. The predicate can ensure that the script transfers some or all of an asset to the contract.

wow, nice idea.
can you give me a quick code example, or explain how i can use the script to send the funds to a contract.
also amazing repo you had, the gasless-nft was really creative, i got a lot of inspiration from it.

you said the predicate can enforce, the script sends funds via a smart contract call, but i want the predicate to hold the funds, idk i’m honestly confused.

Glad that nft repo was helpful!

That repo actually has a good example, the gas predicate calls tx_script_bytecode_hash() and checks that the script hash matches a stored hash. And the script in question has some logic.

If you want a predicate to send funds to a contract, you can make a script like this:

script;

fn main(amount: u64) {
  let mut coin_amount = 0;
  let mut i = 0;
  while (i < input_count()) {
    if (input_asset(i) ==ASSET_ID) {
      coin_amount += input_amount(i);
    }
  }
  
  transfer(Identity::Contract(CONTRACT_ID), ASSET_ID, coin_amount);
}

And a predicate like this:

predicate;

fn main() {
  let script_bytecode_hash: b256 = tx_script_bytecode_hash();
  if (script_bytecode_hash != EXPECTED_SCRIPT_HASH) {
    return false;
  }
  return true;
}

Wow, so are you saying that combining them, both, the predicate will allow the script spend it’s funds, sending to to the specified contracts?
can you give me a quick cap of how this is possible on a lower level, so i can easily debug errors if i come across.
also, when writing the tests will i have to specify output::variables, or input::contracts?
how will i have to specify to avoid, incorrect transactions.

Wow, so are you saying that combining them, both, the predicate will allow the script spend it’s funds, sending to to the specified contracts?

Pretty much! Any coins that are included as “inputs” that aren’t immediately spent on “outputs” are available to the script. And the script can transfer them to contracts, to variable outputs, etc. And any coins that aren’t spent in CoinOutputs and aren’t spent in the scripts end up in ChangeOutputs.

I would test the script and the predicate separately: make sure the script transfers funds correctly, and separately make sure the predicate enforces the script.

1 Like

testing right now!, please include in the fuel docs, this will open up new ideas for the use of predicates.
Thank you so much.

1 Like

After so many trials it worked.

running 1 test
previous balance of contract: {}
new balance of contract: {0000000000000000000000000000000000000000000000000000000000000000: 5000}
test script_can_transfer ... ok

Thank you so much @david