Multiple native assets in a tx?

I’m aware that a payable function can accept only one asset per transfer. I was wondering how could one best handle a case where multiple native assets are required to be sent to a contract.

An example for such a scenario: a contract that accepts an asset sent from Alice, and sends it to Bob, but the contract itself charges a fee in ETH (BASE_ASSET).

As an example (in Solidity), we might accept a msg.value (ETH) and then also transfer tokens within a contract like so:

function accept_eth_and_tokens() external payable {
    require(msg.value > 0, "Invalid ETH sent");
    IERC20(token).transferFrom(msg.sender, address(this), 420);
}

I suppose a naive implementation would be to batch transactions, but that still defeats the purpose because one cannot enforce within the smart contract that both assets have been successfully sent to the contract. Wondering if a better approach is available?

Hey @theAusicist, you’re right that calls can only include a single asset.

One way you can work-around this and transfer multiple assets is to transfer assets directly to the contract from the script, and have the contract handle it’s own accounting.

For example, you could use a script like this:

script;

main() {
  force_transfer_to_contract(contract_id, my_token, 10);
  let contract = abi(MyContract, contract_id);
  contract.depositAsset{ asset_id: BASE_ASSET_ID, coins: 5 }();
}

And then have a contract like this:

contract;

storage {
  asset_balance: u64 = 0,
}

impl Contract for MyContract {
  #[payable]
  depositAsset() {
    require(asset_id() == BASE_ASSET_ID && msg_amount() == 5);
    
    let amount_sent = this_balance(deposit_asset_id) - storage.asset_balance.read();
    require(amount_sent == 10);
    storage.asset_balance.write(this_balance(deposit_asset_id));
  }
}

thanks! this is similar approach to what I was thinking. Any idea if supporting multiple assets within a single call is being worked on (or on the roadmap or similar)? Would be super cool to have a feature like so!