Multiple SRC20 transfers in single transaction

In the Fuel VM it is not possible to send a SRC20 token to a contract, and then have the contract send the SRC20 token back to you in a single transaction.

The following transfer is not possible in the Fuel VM:

A => B => A

Where user A sends an SRC20 token to contract B and then contract B returns the SRC20 token back to user A, all within the same transaction.

I was wondering where is this specified in the Fuel documentation? Where can I find a good link that references this constraint of the Fuel VM?

6 Likes

It’s definitely possible to have a transaction like this!

Here’s some simple Sway code for a smart contract that will return the funds sent to it:

contract;
use std::{
    call_frames::msg_asset_id,
    context::msg_amount,
};


impl Returner for Contract {
    #[payable]
    fn return_funds(recipient: Identity) {
        transfer(recipient, msg_asset_id(), msg_amount());
    }
}

A user would then call return_funds(), including an asset in the call and the user’s address as the recipient.

1 Like

This conflicts with what other Fuel engineers have mentioned in various telegram chats.

Alexander John Lee:
Hello all, just want to tripple check. In the Fuel VM it is not possible to send a SRC20 token to a contract, and then have the contract send the SRC20 token back to you in a single transaction. Is this true? If so, is there a link to this VM nuance in the docs?

Egor:
Yes, you’re correct. In the Fuel VM, it is not possible to send an SRC20 token to a contract and have the contract send the SRC20 token back to you in a single transaction.

I also have heard this from other Fuel engineers, would reference these messages, however, these are from private chats I no longer have access to.

@david The code snippet provided:

contract;
use std::{
    call_frames::msg_asset_id,
    context::msg_amount,
};


impl Returner for Contract {
    #[payable]
    fn return_funds(recipient: Identity) {
        transfer(recipient, msg_asset_id(), msg_amount());
    }
}

when executed reverts.

@david

I got your code snippet to work. I wasn’t using VariableOutputPolicy correctly.

    #[payable]
    fn return_funds() {
        transfer(msg_sender().unwrap(), msg_asset_id(), msg_amount());
    }

When calling the function like this in Rust, the transaction succeeds.

    let call_params = CallParameters::new(amount, underlying_asset, 100_000);
    let tx_test= instance.methods()
    .return_funds()
    .call_params(call_params.clone())?
    .with_variable_output_policy(VariableOutputPolicy::Exactly(1))
    .call()
    .await?;

Just got a bit confused when I was told by 2 other people at Fuel that this type of transaction was not possible. Turns out it is!!!

Thank you for your help.

It seems like there was some confusion regarding this functionality, but it looks like it’s actually possible to send an SRC20 token to a contract and have it returned in the same transaction, as demonstrated with the correct usage of VariableOutputPolicy. Glad to hear it worked after sorting out the configuration. It might be helpful for the documentation to clarify this point, as it seems there was a misunderstanding about the Fuel VM’s capabilities!