How to send money from predicate to owner back

Have tried to make predicate.transfer to creator back as it was described in this tutorial, but face Error: not enough resources to fit the target

code :

const configurableConstants = {
      ASSET0: token0,
      ASSET1: token1,
      PRICE: price.toFixed(0),
      MAKER: this.rootStore.accountStore.ethFormatWallet,
    };

const predicate = new Predicate(
  PREDICATE_BYTECODE,
  PREDICATE_ABI,
  this.rootStore.accountStore.provider,
  configurableConstants
);
const tx1 = await wallet.transfer(predicate.address, amount, token0);
console.log("tx1", tx1);
await tx1.waitForResult();

const tx2 = await predicate.transfer(wallet.address, amount, token0);
console.log("tx2", tx2);
await tx2.waitForResult();

link to predicate code - here

Error message

But also I realised that there is no signing from owner to cancel this predicate, so this transfer would be same if I just create Wallet instance from public address and make transfer . What am I doing wrong in this code example?

5 Likes

Hi @sway , couple issues I can see:

  1. The error could relate to either of the transfer calls, either the wallet does not have enough token0 to fund the predicate, or the predicate doesn’t have enough token0 at the time of evaluating the predicate. This is also dependent on the value of amount at the time both of those transactions are called. You can call getBalance(token0) on either the wallet or predicate instance to check the resources available prior to calling transfer.
  2. The configurableConstants object in your TS code does not contain the same number of values as the configurable declared in your sway predicate, this will produce a validation error (different error to above).
1 Like

I haven’t tried to run the code but it looks like when you do predicate.transfer, you’re trying to transfer all balance that the predicate has, but in that case there are no coins left to cover gas fees. When you call predicate.transfer, the only inputs of the transaction are the UTXOs owned by the predicate, so they should include coins to pay for the fee as well.

You can either try to transfer a slightly lower amount or build the transaction yourself and provide only one output of type ChangeOutput (instead of CoinOutput) - that way all predicate coins except fees will be transferred to the receiver and after the tx predicate won’t have any coins left.

2 Likes

thanks for reply

abt passing not enough data as configurable by the time when I was creating this topic predicate code didn’t relay on MIN_FULFILL_AMOUNT0 , so lets assume that predicate doesn’t need MIN_FULFILL_AMOUNT0 , btw predicate creation was sucsesfull

and abt checking predicate balances like this

const configurableConstants = {
      ASSET0: token0,
      ASSET1: token1,
      PRICE: price.toFixed(0),
      MAKER: this.rootStore.accountStore.ethFormatWallet,
    };
    try {
      const predicate = new Predicate(
        PREDICATE_BYTECODE,
        PREDICATE_ABI,
        this.rootStore.accountStore.provider,
        configurableConstants
      );

      const initialPredicateBalance = await predicate.getBalance(token0);
      console.log("initialPredicateBalance", initialPredicateBalance);

      console.log("wallet.transfer", amount);
      const tx1 = await wallet.transfer(predicate.address, amount, token0);
      // console.log("tx1", tx1);
      await tx1.waitForResult();

      const feetx = await wallet.transfer(predicate.address, 50);
      await feetx.waitForResult();
      // console.log("feetx", feetx);

      const prediBalance = await predicate.getBalances();
      console.log("prediBalances", prediBalance);

      console.log("predicate.transfer", amount);
      const tx2 = await predicate.transfer(wallet.address, amount, token0);
      // console.log("tx2", tx2);
      await tx2.waitForResult();

      const finalPredicateBalance = await predicate.getBalance(token0);
      console.log("finalPredicateBalance", finalPredicateBalance);

      // if (tx.id != null)
      //   this.notifyThatActionIsSuccessful("Order has bee placed", tx.id);
    } catch (e: unknown) {
      console.error(e);
    } finally {
      this.setLoading(false);
    }

after I added ETH transfer to predicate for gas error changed to this one

Assume that I need to send inputs/outputs for transfer call to pass this one, please check this one - Predicates With Configurable Constants | Fuels-ts (seems to be wrong)

good idea! added ETH transfer to pay gas fee and error changed, check it in message above

As I see it, the error basically says that the predicate returned false. You can try it out with a more simple predicate like the one that always returns true and then add new checks step by step. It’s a pain that right now you can’t debug predicates in other way

2 Likes

@sway thanks for bringing that up.

For your first question, it seems like the error is happening because the predicate is trying to transfer all locked funds, leaving nothing for the transaction fees. I’m actually in the process of revising a doc page on how to send and spend funds from a predicate, so your input is valuable. I’ll make sure to add this info to the doc page.

For the second issue, this is happening because the predicate is returning false. If that wasn’t supposed to happen I’ll need to take a look at your predicate code and your use case. Could you share more details? I’m keen to help figure out what’s going on.

Thanks!

1 Like